Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

New C features proposal

29 views
Skip to first unread message

Michal Nazarewicz

unread,
Apr 18, 2010, 5:00:46 PM4/18/10
to
Hello everyone,

As the committee gathered to discuss how the new C standard will look
like I did some thinking of my own. I thought about features that
I would love to see in C. I even collected thoughts of my twisted mind
and condensed them into a text file.

What is outrageous is that since I believe information and ideas want to
be free and shared I have decided to post my concepts on the net instead
of imprisoning them in my wicked brain.

Maybe someone will find it useful somehow. Maybe even some committee
member will read those and bring them out on next meeting. In any case,
feel free to ignore this thread. :)

(BTW. An HTML version of this post can be found at the following
address: <URL:http://mina86.com/2010/04/18/new-c-features-proposal/>.)


I *Default Function Argument*

1. The default value of a function's argument has proved to be useful
in C++ programs as well as in other languages which has such
a notion. It allows for more condensed function call in the usual
cases still allowing for a configuration when required.

2. Syntax and semantics of such feature should be the same as in C++.

3. Example:

#v+
struct node {
struct node *next;
int key;
const char *value;
};

struct void *get(struct node *first, int key, const char *def = NULL) {
for (; first; first = first->next) {
if (first->key == key)
return first->value;
return def;
}
#v-

4. In the current standard, such syntax it is invalid thus it will
not affect existing code. Moreover, many C implementations are
also capable of accepting C++ code thus implementing this feature
would be an easy task in many such cases.


II *Named Arguments*

1. It has been observed that calls to functions with many arguments
are somehow unreadable since it is hard to keep track of which
argument means what.

2. To mitigate this problem named arguments could be added to the
C language with a syntax similar to one used in structures and
union initialisation.

3. Example:

#v+
void message(const char *msg,
enum level .level, enum colour .colour);

/* ... */
message("A message", .level = LVL_INFO, .colour = WHITE);
message("An error", .colour = RED, .level = LVL_ERROR);
#v-

4. The name of the argument would become part of a function's
prototype thus the following would be illegal:

#v+
void f1(int .bar);
void f1(int .baz); /* different name */
void f2(int bar);
void f2(int .bar); /* unnamed vs. unnamed */
#v-

5. If different names (or lack of names) was used in different
translation unit behaviour would be still well defined as long as
order and types of arguments match.

6. Similarly, when taking function's address or casting between
pointers to functions the names of arguments would be ignored,
hence the following would be still well defined and perfectly
legal:

#v+
int cmp(const void *.a, const void *.b)

int arr[10];

qsort(arr, sizeof arr / sizeof *arr, sizeof *arr, cmp);
cmp(.a = &arr[0], .b = &arr[1]);

int (*foo)(const void *.x, const void *.y);
foo = cmp;
foo(.x = &arr[0], .y = &arr[1]);
/* same as cmp(.a = &arr[0], .b = &arr[1]) */

int (*bar)(const void *.b, const void *.a);
bar = cmp;
bar(.a = &arr[0], .b = &arr[1]);
/* same as cmp(.a = &arr[1], .b = &arr[0]) */
#v-

7. Named arguments would have to be specified using their name, thus,
with earlier `message()` declaration, the following would be
invalid:

#v+
message("A message", LVL_INFO, WHITE);
#v-

8. Since the name of the argument would have to be specified, they
could appear in any order, intermixed with unnamed arguments. For
instance:

#v+
void format(const char *format,
enum level .level, enum colour .colour,
...) {
va_list ap;

/* ... do something with level and colour ... */

va_start(ap, colour);
vprintf(format, ap);
va_end(ap);
putchar('\n');
}

format("%s is ready", dish_name,
.level = LVL_INFO, .colour = WHITE);
format(.level = LVL_ERROR, .colour = READ,
"%s is burnt", cake_name);
format("we are out of %s",
.level = LVL_WARN, .colour = WHITE,
resource_name);
#v-

9. Proposed syntax is an invalid syntax in the current standard so
this change would not impact existing code. At the same time,
implementations use such syntax in initialisation list thus it
would be simplified to use the same syntax in named arguments.

10. Named arguments would be especially powerful with conjunction with
default value. In particular, `format()` could be defined as:

#v+
void format(const char *format,
enum level .level = LVL_INFO,
enum colour .colour = WHITE,
...);
#v-

And then, previous calls could be shortened to:

#v+
format("%s is ready", dish_name);
format(.level = LVL_ERROR, .colour = READ,
"%s is burnt", cake_name);
format("we are out of %s",
.level = LVL_WARN,
resource_name);
#v-


III *Inlined Structures and Unions*

1. The new standard draft allow declaration of anonymous structures
and anonymous unions in structures and unions:

#v+
struct {
union {
int i;
struct {
short s;
char c;
};
};
} a;

/* All valid: */
a.i;
a.s;
a.c;
#v-

2. This technique is used already by some C implementations and has
proved useful however is limited to a simple case. A syntax where
by using `inline` keyword one could achieve similar effect for
named structures (especially defined elsewhere) or fields that
otherwise have name could be handy.

3. Proposed syntax looks as follows:

#v+
inlined-member:
structure-or-union-type identifier_{opt} "inline"
inline-list_{opt}

inline-list:
"(" identifiers-list_{opt} ")"
"(" identifiers-list_{opt} "," ")"

identifiers-list:
identifier
identifiers-list "," identifier
#v-

4. The `inline` keyword would mean that all the members of the
structure or union are accessible from namespace the declaration
is in.

5. An optional list of identifier would make only listed identifiers
be accessible from the namespace. An empty list would mean no
identifiers would be inlined but this would be useful with
casting -- read further.

6. An optional identifier would allow accessing the structure as
a whole as well as each individual member via the name.

7. Example:

#v+
struct s1 { int i1, j1; };
struct s2 { int i2, j2; };
struct s3 { int i3, j3; };

struct {
struct s1 inline;
struct s2 s inline;
struct s3 a inline(i3);
struct s3 b inline(j3);
} s;

/* To reach each of the fields: */
s.i1;
s.j1;
s.i2; /* same as */ s.s.i2;
s.j2; /* same as */ s.s.j2;
s.i3; /* same as */ s.a.s3;
s.j3; /* same as */ s.b.j3;
s.a.j3;
s.b.i3;
#v-

8. This allows to nicely build structures that share some common
data. For instance:

#v+
struct header_head {
unsigned length;
unsigned type;
};

struct foo_header {
struct header_head inline;
unsigned some_field_1;
unsigned some_field_2
};

struct bar_header {
struct header_head inline;
unsigned some_field_1;
unsigned some_field_2
};

union header {
struct header_head inline;
struct foo_header foo;
struct bar_header foo;
};


union header header;
if (header.type == FOO_HEADER_TYPE) {
handle_foo(&header.foo);
} else if (header.type == BAR_HEADER_TYPE) {
handle_foo(&header.bar);
} else {
error();
}
#v-

9. This would not be limited to defining structure's or union's
members but could be used in other scopes. For instance:

#v+
void do_stuff(int use_double) {
union {
float f;
double d;
} inline;
if (use_double)
/* ... do stuff using "d" */
else
/* ... do stuff using "f" */
}
#v-

10. Proposed syntax is not valid C99 syntax so it would not affect
existing code.


IV *Casting to Inlined Members*

1. Inlined structures and unions would be especially powerful if
implicit casting to an inlined member was allowed. This would
allow for an object oriented programming without the need for
explicit cast and/or run-time checking.

2. Example:

#v+
struct point {
double x, y;
};
struct circle {
struct point inline;
double r;
};

void moveBy(struct point *p, double x, double y) {
p->x += x;
p->y += y;
}

void paintCircle(struct circle *c);

struct circle *c;
for (int i = 0; i < 10; ++i) {
paintCircle(c);
moveBy(c, 1.0, 1.0);
}
#v-

3. Should implicit cast be ambiguous it should be disallowed, ie.:

#v+
struct rectangle {
struct point tl inline(x, y);
struct point br inline();
};

struct rectangle *r;
moveBy(r, 1.0, 1.0); /* illegal */
#v-

4. For compatibility reasons, an explicit cast to a pointer to a type
of one of inlined member would produce different results.

5. Explicit casting to inlined member would not need to be supported
by the language as users could name an inlined member and use "&"
operator to acquire it's address. For instance:

#v+
moveBy(&r->tl, 1.0, 1.0);
moveBy(&r->br, 1.0, 1.0);
#v-

6. Implicit casting of a pointer to one structure or unione to
a pointer to another structure or union is not valid thus this
change would not affect exiting code.


V *The `_Containerof` operator*

1. User may sometimes face the following problem: Having pointer to
a member of a structure how do I get pointer to the structure?
This would be especially useful with conjunction with inlined
members and implicit casting to inlined members (as I will show).

2. To solve this issue the following construct, similar to one used
in the Linux kernel, could be used:

#v+
type *_Containerof(pointer, type, accessor);
#v-

3. Where accessor would be a list of identifiers separated by a dot
such that if X was an object of type type then X.accessor would
yield an object of type the same as *pointer.

4. The result of the construct would be a pointer to an object X of
type type such that &X->accessor == pointer.

5. For inlined members, either of the following variants could be
used:

#v+
type *_Containerof(pointer, type);
type *_Containerof(pointer, type, auto);
#v-

(I'll assume the former in the rest of the text.)

6. Since identifiers starting with an underscore followed by an
upper-case letter are reserved for further version of the standard
this change would not affect conforming programs.

7. A C1x specific header (for instance `stdc1x.h`) could be provided
which would define a `containerof()` macro, as:

#v+
#define containerof(...) _Containerof(__VA_ARGS)
#v-


VI *Object Oriented Programming*

1. All of the above features would allow for an object oriented
programming with minimal need for implicit casts and/or run-time
checking:

#v+
struct point {
double x, y;
};

void point_init(struct point *p,
double x = 0.0, double y = 0.0) {
p->x = x;
p->y = y;
}


struct figure {
const struct figure_vtab *vtab;
struct point inline;
};

struct figure_vtab {
double (*area)(struct figure *f);
};

void figure_move_by(struct figure *f, double x, double y) {
f->x += x;
f->y += y;
}

double figure_area(struct figure *f) {
return f->vtab->area(f);
}

void figure_init(struct figure *f,
double x = 0.0, double y = 0.0) {
point_init(f, x, y);
}


struct circle {
struct figure inline;
double r;
};

double circle_area_vtab(struct figure *f) {
struct circle *c = containerof(f, struct circle);
return M_PI * r * r;
}

void circle_init(struct circle *c, double x = 0.0, double y = 0.0,
double r = 1.0) {
figure_init(c, x, y);
c->r = r;

c->vtab = &(const struct figure_vtab){
.area = circle_area_vtab,
};
}


struct rectangle {
struct figure inline;
double width;
double height;
};

double rectangle_area_vtab(struct figure *f) {
struct rectangle *r = containerof(f, struct rectangle);
return r->width * r->height;
}

void rectangle_init(struct circle *c, double x = 0.0, double y = 0.0,
double w = 1.0, double h = 1.0) {
figure_init(c, x, y);
c->width = w;
c->height = h;

c->vtab = &(const struct figure_vtab){
.area = rectangle_area_vtab,
};
}
#v-


VII *Function Overloading*

1. Function overloading is a feature that may help programmer
concentrate on the general idea of the code he or she is
developing without thinking too much about types that are being
used.

2. Function declared in `math.h` are perfect example of such
situation. Existence of functions such as `sin`, `sinf` and
`sinl` force programmer to think about underlying type whereas it
may not be that important.

3. The situation goes worse when one decides that a different type is
to be used. In such situation, all calls to type-dependent
functions have to be traced and replaced. This operation is
rather boring and error-prone.

4. Situation gets even more complicated when one wants to develop
a code where the type used is dependent on a macro definition or
a typedef. This may be even more tricky if the macro/typedef
comes from the external library and there's no clear way of
telling what type it is during prepossessing stage.

5. All such situations would be trivial if function overloading was
allowed.

6. To maximise compatibility with older implementations a syntax
taken from C++ could be used for functions with external linkage:

#v+
extern "C++" float mysin(float x) { return sinf(x); }
extern "C++" float mysin(double x) { return sin(x); }
extern "C++" float mysin(long double x) { return sinl(x); }
#v-

and analogous syntax far functions with internal linkage:

#v+
static "C++" float mysin(float x) { return sinf(x); }
static "C++" float mysin(double x) { return sin(x); }
static "C++" float mysin(long double x) { return sinl(x); }
#v-

7. In the current standard, function overloading is invalid thus it
will not affect existing code. Moreover, many C implementations
are also capable of accepting C++ code thus implementing this
feature would be an easy task in many such cases.


VIII *Type Agnostic Limits Functions*

1. Macros defined in the `limits.h` header suffer from the same
problems described above. It would be nice to have constructs
such as `_Type_min`, `_Type_max`, etc. which, the same as
`sizeof`, take an expression or type as an argument and return the
smallest, biggest, etc. value representable by the type.

2. Identifiers starting by an underscore followed by capital letter
are reserved thus this feature would not affect existing code.


IX *Nested Static Functions*

1. It is often desirable to limit a scope of an identifier both to
avoid erroneous usage from outside of the scope or simply not to
pollute the outer scope.

2. User may define static variables in a local scope so why not let
them define static functions in local scope. For instance:

#v+
struct foo;
void sort_foo(struct foo *foos, size_t n) {
static int cmp(const void *_a, const void *_b) {
const struct foo *a = _a, *b = _b;
/* ... */
return /* ... */;
}
qsort(foos, n, sizeof *foos, cmp);
}
#v-

3. Such a function would behave as if it was a normal function expect
it could not be accessed via name from outside of to outer
function and it would have access to all other static functions
and variables defined in the same scope prior to itself.

4. Current standard does not allow function nesting thus this change
would have no effect on existing code.


XI *Compound Functions*

1. The current standard have introduced compound literals for
defining unnamed static objects. The same syntax could be used
to define functions:

#v+
struct foo;
void sort_foo(struct foo *foos, size_t n) {
qsort(foos, n, sizeof *foos,
(int ()(const void *_a, const void *_b)){
const struct foo *a = _a, *b = _b;
/* ... */
return /* ... */;
});
}
#v-

2. This change would prevent namespace pollution and allow for
shorter notation for callback functions. It would also look quite
familiar for users familiar with functional programming.

3. In the current standard such syntax is invalid thus this change
would not affect existing code.


X *Unnamed Arguments*

1. It sometimes happens that a function takes an argument but does
not use it. This most common for callback functions or "virtual
methods" when simulating object oriented programing.

2. At the same time, some implementations allow to turn diagnostics
informing of unused variables on. Such diagnostics may help in
identifying problems in the code.

3. However, when the two above combined, warnings about unused
arguments are produced when it is user's intend no to use them.
Common technique is to cast such an argument to void at the
beginning of a function to silence the warning.

4. C++ allows for a name of an argument to be omitted in function
definition which solves the above problem. The same could be
implemented in C.

5. The current standard requires names to be present for all
function's arguments in function definition so this change would
not affect conforming code. At the same time, many
C implementations are also capable of compiling C++ code thus
implementing this feature could be easy and straightforward.


XII *The `alignof` operator*

1. The new C standard draft proposes an `alignof` operator that
takes type as it's operand. Why cannot it take an expression as
it's operand the same way `sizeof` does?

2. The `alignof` operator is added in the new standard thus this
change would not impact existing code any further then adding the
`alignof` did itself.

3. Since in the current standard, `alignof` is perfectly valid
identifier, why not define an `_Alignof` operator and add
a `stdc1x.h` header with the following macro:

#v+
#define alignof _Alignof
#v-


XIII *The Tags*

1. Even though structures, unions and enumerations use different word
for identifying the type, they still use the same namespace for
tags. In particular, the following is invalid:

#v+
struct foo { int a; };
union foo { int b; char c; };
enum foo { A, B, C };
#v-

2. How about using different namespaces for those tags?


--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86-tlen.pl>--<jid:mina86-jabber.org>--ooO--(_)--Ooo--

Keith Thompson

unread,
Apr 18, 2010, 8:40:14 PM4/18/10
to
Michal Nazarewicz <min...@tlen.pl> writes:
[...]

Just one quick comment; I might have more to say later.

> IV *Casting to Inlined Members*
>
> 1. Inlined structures and unions would be especially powerful if
> implicit casting to an inlined member was allowed. This would
> allow for an object oriented programming without the need for
> explicit cast and/or run-time checking.


The phrase "implicit casting" makes no sense. A cast is an operator
that specifies a conversion. You mean "implicit conversion".

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Michal Nazarewicz

unread,
Apr 19, 2010, 2:08:49 AM4/19/10
to
> Michal Nazarewicz <min...@tlen.pl> writes:
>> IV *Casting to Inlined Members*
>>
>> 1. Inlined structures and unions would be especially powerful if
>> implicit casting to an inlined member was allowed. This would
>> allow for an object oriented programming without the need for
>> explicit cast and/or run-time checking.

Keith Thompson <ks...@mib.org> writes:
> The phrase "implicit casting" makes no sense. A cast is an operator
> that specifies a conversion. You mean "implicit conversion".

Thanks for pointing that out. Even though I like to think I know
standard to some degree I wasn't aware of that.

jacob navia

unread,
Apr 19, 2010, 6:03:54 AM4/19/10
to
Michal Nazarewicz a écrit :

>> Michal Nazarewicz <min...@tlen.pl> writes:
>>> IV *Casting to Inlined Members*
>>>
>>> 1. Inlined structures and unions would be especially powerful if
>>> implicit casting to an inlined member was allowed. This would
>>> allow for an object oriented programming without the need for
>>> explicit cast and/or run-time checking.
>
> Keith Thompson <ks...@mib.org> writes:
>> The phrase "implicit casting" makes no sense. A cast is an operator
>> that specifies a conversion. You mean "implicit conversion".
>
> Thanks for pointing that out. Even though I like to think I know
> standard to some degree I wasn't aware of that.
>
ALl casts are conversions from one type to another.
Forget thmpson, he just likes to posts this kind of messages so he looks important.

jacob navia

unread,
Apr 19, 2010, 6:07:05 AM4/19/10
to
Some of your poposals are implemented in the lcc-win C compiler.
Default function arguments for instance, generic functions.

I have been proposing those things here for years but this newsgroup
has nothing to do with the committee.

There is a proposition in the committee now to eliminate some of the
timid features of C99 so I think that there is no possibility of
them approving anything innovating.

Seebs

unread,
Apr 19, 2010, 10:35:20 AM4/19/10
to
On 2010-04-19, jacob navia <ja...@nospam.org> wrote:
> I have been proposing those things here for years but this newsgroup
> has nothing to do with the committee.

Well, a few people involved in the committee read and discuss in this
newsgroup.

> There is a proposition in the committee now to eliminate some of the
> timid features of C99 so I think that there is no possibility of
> them approving anything innovating.

Such as, say, some threading support?

Your inability to accept data that don't confirm your pessimism is
really disturbing.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Keith Thompson

unread,
Apr 19, 2010, 11:13:36 AM4/19/10
to
jacob navia <ja...@nospam.org> writes:
> Michal Nazarewicz a écrit :
> >> Michal Nazarewicz <min...@tlen.pl> writes:
> >>> IV *Casting to Inlined Members*
> >>>
> >>> 1. Inlined structures and unions would be especially powerful if
> >>> implicit casting to an inlined member was allowed. This would
> >>> allow for an object oriented programming without the need for
> >>> explicit cast and/or run-time checking.
> > Keith Thompson <ks...@mib.org> writes:
> >> The phrase "implicit casting" makes no sense. A cast is an operator
> >> that specifies a conversion. You mean "implicit conversion".
> > Thanks for pointing that out. Even though I like to think I know
> > standard to some degree I wasn't aware of that.
> >
> ALl casts are conversions from one type to another.

Yes, but not all conversions are casts. For example, in the
following:

double x = 42;

there's an implicit conversion from int to double. There is no cast.

You've written a compiler, jacob; surely you know that.

> Forget thmpson, he just likes to posts this kind of messages so he
> looks important.

Deliberately misspelling my name does not improve your credibility.

jacob navia

unread,
Apr 19, 2010, 4:02:53 PM4/19/10
to
Seebs a écrit :

> On 2010-04-19, jacob navia <ja...@nospam.org> wrote:
>> I have been proposing those things here for years but this newsgroup
>> has nothing to do with the committee.
>
> Well, a few people involved in the committee read and discuss in this
> newsgroup.
>
>> There is a proposition in the committee now to eliminate some of the
>> timid features of C99 so I think that there is no possibility of
>> them approving anything innovating.
>
> Such as, say, some threading support?
>
> Your inability to accept data that don't confirm your pessimism is
> really disturbing.
>
> -s

The feature is not mandatory, it suffices to define a symbol and there,
no thread support.

(If the proposal of plauger is accepted)

Seebs

unread,
Apr 19, 2010, 5:07:34 PM4/19/10
to
On 2010-04-19, jacob navia <ja...@spamsink.net> wrote:
> The feature is not mandatory, it suffices to define a symbol and there,
> no thread support.

So what? It's still unambiguously new feature work in the standard.

Of course not everything becomes mandatory.

Keith Thompson

unread,
Apr 19, 2010, 5:42:39 PM4/19/10
to
Seebs <usenet...@seebs.net> writes:
> On 2010-04-19, jacob navia <ja...@spamsink.net> wrote:
> > The feature is not mandatory, it suffices to define a symbol and there,
> > no thread support.
>
> So what? It's still unambiguously new feature work in the standard.
>
> Of course not everything becomes mandatory.

And in this particular case, the feature will be optional *only* if
P.J. Plauger's proposal

<http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1443.htm>

is accepted. As of the N1425 draft, threading is just another
language/library feature, with no indication that it's optional for
hosted implementations.

Background: Plauger proposes making complex arithmetic, threads,
and VLAs, and possibly atomics, optional in C201X. I have no idea
how likely this proposal is to be accepted. I personally dislike
the idea.

Seebs

unread,
Apr 19, 2010, 6:04:45 PM4/19/10
to
On 2010-04-19, Keith Thompson <ks...@mib.org> wrote:
> Background: Plauger proposes making complex arithmetic, threads,
> and VLAs, and possibly atomics, optional in C201X. I have no idea
> how likely this proposal is to be accepted. I personally dislike
> the idea.

I am torn. I recognize the issues in imposing these additional
costs on implementations, but... VLAs have been awfully useful to me
in cases where I have reasonable confidence that it's cheap to
allocate something of about the right size and I won't run out of
room.

Morris Keesan

unread,
Apr 19, 2010, 11:29:42 PM4/19/10
to
On Mon, 19 Apr 2010 06:03:54 -0400, jacob navia <ja...@nospam.org> wrote:

> ALl casts are conversions from one type to another.

(char *)"Oh, really?"

C99 6.5.4, paragraph 4, third sentence: "A cast that specifies no
conversion has no effect on the type or value of an expression."

--
Morris Keesan -- mke...@post.harvard.edu

jacob navia

unread,
Apr 20, 2010, 3:16:38 AM4/20/10
to
Morris Keesan a écrit :

> On Mon, 19 Apr 2010 06:03:54 -0400, jacob navia <ja...@nospam.org> wrote:
>
>> ALl casts are conversions from one type to another.
>
> (char *)"Oh, really?"
>
> C99 6.5.4, paragraph 4, third sentence: "A cast that specifies no
> conversion has no effect on the type or value of an expression."
>

That CONFIRMS what I said: if there is no conversion nothing happens!

THEN

All casts are conversions. When there is no conversion there is no effect.


You can go on splitting hairs of course, it is a national sport here

Walter Banks

unread,
Apr 20, 2010, 9:02:05 AM4/20/10
to

Seebs wrote:

> On 2010-04-19, Keith Thompson <ks...@mib.org> wrote:
> > Background: Plauger proposes making complex arithmetic, threads,
> > and VLAs, and possibly atomics, optional in C201X. I have no idea
> > how likely this proposal is to be accepted. I personally dislike
> > the idea.
>
> I am torn. I recognize the issues in imposing these additional
> costs on implementations, but... VLAs have been awfully useful to me
> in cases where I have reasonable confidence that it's cheap to
> allocate something of about the right size and I won't run out of
> room.
>

In general terms I like Bill's proposal.

We primarily create tools for non-hosted embedded systems that don't
for the most part use float or complex and do use IEC\ISO 18037.
In embedded systems LVA's have a different problem. Run time
memory allocation is viewed as potential failure mode that can
cause the whole system to fail. (Backed by some spectacular
failures)

I think that some refinements to the proposal needs to be considered.
Now may the time to re-visit some of the implementation defined
specifications. We have targeted 28 processors and many of
implementation defined issues probably could be defined with
very little impact on code generation. I suspect that most of
the compiler developers in WG-14 would agree on the
implementation of most of the implementation defined parts
of the standard

The proposal also opens (for us) the idea of a conforming C
compiler that has some specific implementation part that is
non conforming. For example two of our compilers have non
standard floating point implementations so that the hardware
may be better used, the remaining parts could be easily validated.

Regards,


Walter..
--
Walter Banks
Byte Craft Limited
http://www.bytecraft.com

Antoine Leca

unread,
Apr 20, 2010, 11:07:30 AM4/20/10
to
Michal Nazarewicz wrote:
> II *Named Arguments*

> 7. Named arguments would have to be specified using their name, thus,
> with earlier `message()` declaration, the following would be
> invalid:
>
> #v+
> message("A message", LVL_INFO, WHITE);
> #v-

While the general idea about named argument is interesting, I do not
like that point.

It requires *both* the prototypes (part of the implementation of a
library, usually as a .h) and the actual use to be in sync, that is
using either the C90-style prototypes and function calls *or* the
new-syntax prototypes and function calls.

As a consequence, this prevents this new feature to be used for the
standard library, since it would break more than 90% of present day code
(strangely, code using old-style definitions would still work); the same
argument applies to any existing library, it would cause integration of
it to require a rewriting of all the code which use it, thus creating a
new API; I see it as a hint the feature does not integrate smoothly.


This problem also backfires the implementation. You said

> 4. The name of the argument would become part of a function's
> prototype thus the following would be illegal:
>
> #v+
> void f1(int .bar);
> void f1(int .baz); /* different name */
> void f2(int bar);
> void f2(int .bar); /* unnamed vs. unnamed */
> #v-

So, assuming we have

/* header.h */
void f1(int .bar);

What the actual implementation of f1 would look like?
I foresee two solutions:
1) in the grand tradition of C preprocessor hacks, header.h really is

/* header.h */
#ifndef _
#define _(p) p
#endif

void f1 _((int .bar));

and then header.c would look like:

/* header.c */
#define _(p) () /* prevent the prototypes to come in */
#include "header.h" /* but get the structures and typedefs*/

void f1 (int bar)
{
// ... details omitted

2) additionnally to the proposal, arguments in the form .bar can be
aliased in some way in the function definition; something along the
lines of (== is just a placeholder, insert any symbol you prefer)

/* header.c */
#include "header.h"

void f1 (int foo == .bar)
{
// ... and then the code uses "foo" as parameter

(Of course "foo" can be actually spelled "bar".)

Neither solution I find attractive (yes, it is an understatement).

A third solution is to use .bar in the function definition body as well;
it definitively looks strange to me, and I notice you did not provide
examples. Also it could require a more complex parsing, and potential
conflicts; feel free to write the yacc grammar which show me wrong.


As a bottom line, I believe the general point of the charters about
"inventions" still stands here. If this seems a good idea to some
people, it is urgent to actually implement it and to let people use it
to some point. About overloading for example, we all know of
implementations, and I believe there have already been talks in the
committee about that idea (and if it is definitively discarded, it
should been made clearer). Your idea about default argument have already
implementations too (and C++ compatibility, at least I hope so), so
people will have clear ideas too. This one about named argument passing
on the other side is a new syntax, so it ought to be implemented to see
if it works really.

By the way, I have thought of a different syntax:

void message(const char *msg, enum level level=LVL_WARN,
enum sound sound=QUIET, enum colour colour=WHITE);

/* ... */
message("A message", LVL_INFO, .colour = WHITE);
message(.msg = "An error", .colour = RED, .level = LVL_ERROR);

As with several similar syntaxes, unnamed arguments should go first, in
correct order; obviously, there is a defect with varargs functions,
whose (also unnamed) arguments are to be put at the end, as in

format("we are out of %s, wants %d more",
.level = LVL_WARN, .colour = WHITE, /*.sound omitted*/
resource_name, lack);

which is definitively ugly. It is just writing down here without actual
experiment, so the point about potential parsing problem above applies
here too. Just more food for thought.


Antoine

Keith Thompson

unread,
Apr 20, 2010, 11:16:56 AM4/20/10
to
jacob navia <ja...@spamsink.net> writes:
> Morris Keesan a écrit :
> > On Mon, 19 Apr 2010 06:03:54 -0400, jacob navia <ja...@nospam.org> wrote:
> >
> >> ALl casts are conversions from one type to another.
> > (char *)"Oh, really?"
> > C99 6.5.4, paragraph 4, third sentence: "A cast that specifies no
> > conversion has no effect on the type or value of an expression."
> >
>
> That CONFIRMS what I said: if there is no conversion nothing happens!

No, it flatly contradicts what you said. You said that *all* casts
are conversions from one type to another. Morris produced a cast that
is not a conversion from one type to another.

> THEN
>
> All casts are conversions. When there is no conversion there is no effect.

No, not all casts are conversions. We see here a cast that is not a
conversion.

> You can go on splitting hairs of course, it is a national sport here

Ok, the existence of casts that do not specify conversions is not a
huge deal. The standard could just as easily have described this as a
conversion from a type to the same type. You were *nearly* right, and
I didn't notice the special case myself.

But you made the claim in response to something I wrote, in which I
pointed out that there's no such thing as an "implicit cast"; rather,
the OP was really talking about *implicit conversions*. Your claim,
even if it were true, did not address my point.

To summarize:

A cast explicitly specifies a conversion, except in the special
case where the specified type is the same as the operand type,
and no conversion is necessary.

There is no such thing as an implicit cast.

A conversion, on the other hand, may be either explicit (specified
by a cast) or implicit.

If i'm mistaken on any of these points, please demonstrate it.

William Ahern

unread,
Apr 20, 2010, 11:21:30 AM4/20/10
to
Michal Nazarewicz <min...@tlen.pl> wrote:
<snip>

> II *Named Arguments*
>
> 1. It has been observed that calls to functions with many arguments
> are somehow unreadable since it is hard to keep track of which
> argument means what.
>
> 2. To mitigate this problem named arguments could be added to the
> C language with a syntax similar to one used in structures and
> union initialisation.

I used named arguments all the time, although I rely on the fact that GCC
(like perhaps all compilers) will zero-initialize members not specified.

struct foo { int a, b; };
void foo(struct foo f);
#define foo(...) foo((struct foo){ __VA_ARGS__ })

foo(.b = 42);

This technique could be ratified by specifying implicit zero initialization
for auto object initializers and compound literals, and by allowing a member
to be set twice (so that members could be pre-set by the macro to something
other than zero).

Michal Nazarewicz

unread,
Apr 20, 2010, 12:13:40 PM4/20/10
to
> Michal Nazarewicz <min...@tlen.pl> wrote:
> <snip>
>> II *Named Arguments*
>>
>> 1. It has been observed that calls to functions with many arguments
>> are somehow unreadable since it is hard to keep track of which
>> argument means what.
>>
>> 2. To mitigate this problem named arguments could be added to the
>> C language with a syntax similar to one used in structures and
>> union initialisation.

William Ahern <wil...@wilbur.25thandClement.com> writes:
> I used named arguments all the time, although I rely on the fact that GCC
> (like perhaps all compilers) will zero-initialize members not specified.
>
> struct foo { int a, b; };
> void foo(struct foo f);
> #define foo(...) foo((struct foo){ __VA_ARGS__ })
>
> foo(.b = 42);

This has an disadvantage especially on systems with a large number of
registers where function arguments are passed via registers.

Also, can you use compound literals with non-const initialisers? I'd
have to check.

Michal Nazarewicz

unread,
Apr 20, 2010, 1:04:31 PM4/20/10
to
Antoine Leca <ro...@localhost.invalid> writes:

> Michal Nazarewicz wrote:
>> II *Named Arguments*
>> 7. Named arguments would have to be specified using their name, thus,
>> with earlier `message()` declaration, the following would be
>> invalid:
>>
>> #v+
>> message("A message", LVL_INFO, WHITE);
>> #v-
>
> While the general idea about named argument is interesting, I do not
> like that point.
>
> It requires *both* the prototypes (part of the implementation of a
> library, usually as a .h) and the actual use to be in sync, that is
> using either the C90-style prototypes and function calls *or* the
> new-syntax prototypes and function calls.
>
> As a consequence, this prevents this new feature to be used for the
> standard library, since it would break more than 90% of present day code
> (strangely, code using old-style definitions would still work); the same
> argument applies to any existing library, it would cause integration of
> it to require a rewriting of all the code which use it, thus creating a
> new API; I see it as a hint the feature does not integrate smoothly.

Yes, this is an issue but I think it's not as bad as you make it look
like. First of all, the same function could be declared with named
arguments in one translation unit and without in another. This mean
that as long as you are using the same call convection in a single
translation unit you are fine. So for instance, a library could look
like this:

#v+
/* foo.h */
#if USE_NAMED
# define DOT '.'
#else
# define DOT
#endif

int sum(int DOT a, int DOT b);

#under DOT

/* foo.c */
#define USE_NAMED 1

#include "foo.h"

int sum(int .a, int .b) {
return a + b;
}
#v-

The problem arises when, for whatever reason, one wants to mix calling
conventions. This can be somehow solved if we agree to use a different
name for a new syntax, ie:

#v+
int sum(int, int);
static inline int new_sum(int .a, int .b) {
return sum(a, b);
}
#v-

Ideally it would be nice not to have to use tricks like this and choose
whichever calling convection we feel like but that has it's own, in my
opinion bigger, issues which I'll describe further down the post.

I don't see your point here. If the prototype is

#v+
void f1(int .bar);

then the definition would have to be:

void f1(int .bar) {
/* ... */
}
#v-

I also do not see big problem in defining grammar. It's just an
optional dot prior to formal argument name.

>
>
> As a bottom line, I believe the general point of the charters about
> "inventions" still stands here. If this seems a good idea to some
> people, it is urgent to actually implement it and to let people use it
> to some point. About overloading for example, we all know of
> implementations, and I believe there have already been talks in the
> committee about that idea (and if it is definitively discarded, it
> should been made clearer). Your idea about default argument have already
> implementations too (and C++ compatibility, at least I hope so), so
> people will have clear ideas too. This one about named argument passing
> on the other side is a new syntax, so it ought to be implemented to see
> if it works really.
>
> By the way, I have thought of a different syntax:
>
> void message(const char *msg, enum level level=LVL_WARN,
> enum sound sound=QUIET, enum colour colour=WHITE);
>
> /* ... */
> message("A message", LVL_INFO, .colour = WHITE);
> message(.msg = "An error", .colour = RED, .level = LVL_ERROR);

I think this has a disadvantage of postponing error detection to the
point where function is called, ie:

#v+


void message(const char *msg, enum level level=LVL_WARN,
enum sound sound=QUIET, enum colour colour=WHITE);

void message(const char *level, enum level msg=LVL_WARN,
enum sound colour=QUIET, enum colour sound=WHITE);
/* all legal so far */

message(.msg = "An error", .colour = RED, .level = LVL_ERROR);

/* an error at the point of usage call */
#v-

And thus this is why I proposed the names to become part of the
prototype when the new syntax is used in prototype and only then the
argument could be passed as named.

> As with several similar syntaxes, unnamed arguments should go first, in
> correct order; obviously, there is a defect with varargs functions,
> whose (also unnamed) arguments are to be put at the end, as in
>
> format("we are out of %s, wants %d more",
> .level = LVL_WARN, .colour = WHITE, /*.sound omitted*/
> resource_name, lack);
>
> which is definitively ugly. It is just writing down here without actual
> experiment, so the point about potential parsing problem above applies
> here too. Just more food for thought.

This is exactly why named arguments would be required to be called by
name so it's always clear which argument is which.

Again I don't see your point about parsing problems:

#v+
arguments : /* empty */ | arguments_ ;
arguments_: argument | arguments ',' argument ;
argument : expression | '.' ID '=' expression ;
#v-

William Ahern

unread,
Apr 20, 2010, 1:26:36 PM4/20/10
to
Michal Nazarewicz <min...@tlen.pl> wrote:
> > Michal Nazarewicz <min...@tlen.pl> wrote:
> > <snip>
> >> II *Named Arguments*
> >>
> >> 1. It has been observed that calls to functions with many arguments
> >> are somehow unreadable since it is hard to keep track of which
> >> argument means what.
> >>
> >> 2. To mitigate this problem named arguments could be added to the
> >> C language with a syntax similar to one used in structures and
> >> union initialisation.

> William Ahern <wil...@wilbur.25thandClement.com> writes:
> > I used named arguments all the time, although I rely on the fact that GCC
> > (like perhaps all compilers) will zero-initialize members not specified.
> >
> > struct foo { int a, b; };
> > void foo(struct foo f);
> > #define foo(...) foo((struct foo){ __VA_ARGS__ })
> >
> > foo(.b = 42);

> This has an disadvantage especially on systems with a large number of
> registers where function arguments are passed via registers.

Well, in truth I usually pass a pointer to the struct. But I do use this
technique often. For example, creating an iterator construct for my DNS
library:

The relevant header definitions/declarations:

struct dns_rr_i {
enum dns_section section;
enum dns_type type;
/* ... */
};

#define dns_rr_i_new(P, ...) dns_rr_i_init(\
&(struct dns_rr_i){ 0, __VA_ARGS__ }, (P))

struct dns_rr_i *dns_rr_i_init(struct dns_rr_i *, struct dns_packet *);

unsigned dns_rr_grep(struct dns_rr *, unsigned, struct dns_rr_i *, struct dns_packet *, int *);

#define dns_rr_foreach_(rr, P, ...) \
for (struct dns_rr_i XPASTE(i, __LINE__) = \
*dns_rr_i_new((P), __VA_ARGS__); \
dns_rr_grep((rr), 1, &XPASTE(i, __LINE__), (P), &(int){ 0 }); )

#define dns_rr_foreach(...) dns_rr_foreach_(__VA_ARGS__)

Usage, to print out all AAAA answers:

struct dns_packet *pkt;
struct dns_rr rr;
char pretty[512];
size_t len;

...

dns_rr_foreach(&rr, pkt, .section = DNS_S_AN, .type = DNS_T_AAAA) {
if ((len = dns_rr_print(pretty, sizeof pretty, &rr, pkt, &error))) {
fwrite(pretty, 1, len, stdout);
fputc('\n', stdout);
}
}

This little trick blows up some compilers, such as the newly reinvigorated
PCC. But as you can see, the resulting synthetic constructs are *very*
*practical*. And it merely relies on novel compositions of existing C99
capabilities.

Now, perhaps the pre-processor magic is a little unslightly, and I would
agree. But the truth is the vast majority of C code will always use
traditional C patterns, even if the language was redefined to allow every
feature request under the sun. So I think it's enough that some things _can_
be done, even if they're not source-code elegant; they don't necessarily
require that the language provide the cleanest syntax, particularly if such
requirements will in all likelihood be unmet.

Actually, now that I think about it, the above is well-defined, no matter
GCC's complaints. Multiple initializers for the same member are allowed--the
latter alone defining the value--and uninitialized sub-members are
implicitly zero initialized. See 6.7.8(19) (9899:TC3 draft N1256) (my
hardcopy of C99 is boxed up). I suppose my confusion has been with 6.7.8(9),
which says unnamed members have indefined value. I guess the import is that
all top-level structure members should be explicitly initialized; which is
okay with me considering that they can be named in a subsequent
initialization (i.e. from a __VA_ARGS__ in the macro construct above).

> Also, can you use compound literals with non-const initialisers? I'd
> have to check.

Yes. This is allowed if occuring inside the body of a function.

int a = 3, b = 2, c = 1;
int *p = (int [3]){ a, b, c };

But you can't do:

int a = 3, b = 2, c = 1;
int *p = (int [a]){ a, b, c };

But you can do:

int a = 3, b = 2, c = 1;
int *p = (int []){ a, b, c };

In other words, you can't mix VLA and compound literal constructs.
See 6.5.2.5.

Michal Nazarewicz

unread,
Apr 20, 2010, 3:59:09 PM4/20/10
to
>> On 2010-04-19, jacob navia <ja...@spamsink.net> wrote:
>>> The feature is not mandatory, it suffices to define a symbol and
>>> there, no thread support.

> Seebs <usenet...@seebs.net> writes:
>> So what? It's still unambiguously new feature work in the standard.
>>
>> Of course not everything becomes mandatory.

Keith Thompson <ks...@mib.org> writes:
> And in this particular case, the feature will be optional *only* if
> P.J. Plauger's proposal
>
> <http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1443.htm>
>
> is accepted. As of the N1425 draft, threading is just another
> language/library feature, with no indication that it's optional for
> hosted implementations.

Personally, I would go for something I think is more generic, which is
a "_Has" (or #has if you will) preprocessor operator, ie:

#if _Has <stdatomic.h>
# include <stdatomic.h>
#else
# error This program requires stdatomic.h
#endif

a shorthand #ifhas could be provided as well.

This would be more generic in such a way that libraries not covered by
the standard could be checked as well, ie.:

#ifhas <some-funky-library.h>
# include <some-funky-library.h>
#else
/* ... provide a simpler, inferior implementation ... */
#endif

Michal Nazarewicz

unread,
Apr 20, 2010, 3:52:16 PM4/20/10
to
>>> Michal Nazarewicz <min...@tlen.pl> wrote:
>>>> This has an disadvantage especially on systems with a large number
>>>> of registers where function arguments are passed via registers.

William Ahern <wil...@wilbur.25thandClement.com> writes:
> Actually, it just occurred to me that modern ABIs can pass some
> structures via registers. Passing a pointer is thus less efficient.

Can you point to some document that describes that? I don't see how
this can be done. In particular one can do something like:

#v+
void foo(struct foo args) {
struct foo *argsp = &args;
}
#v-

which would imply that the structure would have to be placed in the
memory. As such, I don't see how some of it's elements can be passed
via registers.

William Ahern

unread,
Apr 20, 2010, 3:31:26 PM4/20/10
to
Michal Nazarewicz <min...@tlen.pl> wrote:

> William Ahern <wil...@wilbur.25thandClement.com> writes:
> > Michal Nazarewicz <min...@tlen.pl> wrote:
<snip>
> >> This has an disadvantage especially on systems with a large number of
> >> registers where function arguments are passed via registers.
> >
> > Well, in truth I usually pass a pointer to the struct.

> The same problem. So even though I admit it's an useful technique (and
> in fact I've been wondering about the use of compound literals for
> exactly that purpose) but it would be so much better if we had compiler
> support for such a feature.

Actually, it just occurred to me that modern ABIs can pass some structures

via registers. Passing a pointer is thus less efficient (though efficiency
is not why I do it). This leaves open the question of whether larger
structures are passed on the stack completely, or just the part that
overflows.

Michal Nazarewicz

unread,
Apr 20, 2010, 2:51:46 PM4/20/10
to
William Ahern <wil...@wilbur.25thandClement.com> writes:

> Michal Nazarewicz <min...@tlen.pl> wrote:
>> > Michal Nazarewicz <min...@tlen.pl> wrote:
>> > <snip>
>> >> II *Named Arguments*
>> >>
>> >> 1. It has been observed that calls to functions with many arguments
>> >> are somehow unreadable since it is hard to keep track of which
>> >> argument means what.
>> >>
>> >> 2. To mitigate this problem named arguments could be added to the
>> >> C language with a syntax similar to one used in structures and
>> >> union initialisation.
>
>> William Ahern <wil...@wilbur.25thandClement.com> writes:
>> > I used named arguments all the time, although I rely on the fact that GCC
>> > (like perhaps all compilers) will zero-initialize members not specified.
>> >
>> > struct foo { int a, b; };
>> > void foo(struct foo f);
>> > #define foo(...) foo((struct foo){ __VA_ARGS__ })
>> >
>> > foo(.b = 42);
>
>> This has an disadvantage especially on systems with a large number of
>> registers where function arguments are passed via registers.
>
> Well, in truth I usually pass a pointer to the struct.

The same problem. So even though I admit it's an useful technique (and


in fact I've been wondering about the use of compound literals for
exactly that purpose) but it would be so much better if we had compiler
support for such a feature.

> Now, perhaps the pre-processor magic is a little unslightly, and I would


> agree. But the truth is the vast majority of C code will always use
> traditional C patterns, even if the language was redefined to allow every
> feature request under the sun. So I think it's enough that some things _can_
> be done, even if they're not source-code elegant; they don't necessarily
> require that the language provide the cleanest syntax, particularly if such
> requirements will in all likelihood be unmet.

I don't fully agree. If the feature is useful it will became used and
as times goes by more and more often. The "inline" keyword or names in
initialisation list (the { .foo = ... }, would have to check how it's
called) are an example of that.

Keith Thompson

unread,
Apr 20, 2010, 4:47:10 PM4/20/10
to
Michal Nazarewicz <min...@tlen.pl> writes:
> >>> Michal Nazarewicz <min...@tlen.pl> wrote:
> >>>> This has an disadvantage especially on systems with a large number
> >>>> of registers where function arguments are passed via registers.
>
> William Ahern <wil...@wilbur.25thandClement.com> writes:
> > Actually, it just occurred to me that modern ABIs can pass some
> > structures via registers. Passing a pointer is thus less efficient.
>
> Can you point to some document that describes that? I don't see how
> this can be done. In particular one can do something like:
>
> #v+
> void foo(struct foo args) {
> struct foo *argsp = &args;
> }
> #v-
>
> which would imply that the structure would have to be placed in the
> memory. As such, I don't see how some of it's elements can be passed
> via registers.

It's the same as passing any parameter in a register:

void foo(int arg) {
int *argp = &arg;
}

The parameter passing convention might specify that a parameter
of type int (or of a sufficiently small struct type) is passed in
a certain register. If the function doesn't refer to the address
of the parameter, it can stay in the register. If it does, it has
to be copied to an addressible memory location.

This assume that registers aren't addressible. On some systems,
they might be. The implementation merely has to ensure that the
program's visible behavior matches the standard's requirements.

Keith Thompson

unread,
Apr 20, 2010, 4:57:31 PM4/20/10
to

I like it.

For simplicity, I suggest that the _Has operator should specifically
test whether the named header can be successfully #included, not
whether a library exists. It could of course be applied to any
headers, whether they're specified in the library or not.

Since the most common use is going to be

#if _Has <foo.h>
#include <foo.h>
...

I suggest a shorthand, something like:

#ifinclude <foo.h>
/* <foo.h> has been included */
#else
/* <foo.h> has not been included */
#endif

This could be particularly useful for code that need to work across
versions of the standard. For example, if C90 had had this feature,
you could write:

#ifinclude <stdint.h>
#else
typedef unsigned long uint32_t;
/* Omitted code to check the actual size */
#endif

Yes, strictly speaking you could check __STD_VERSION__, but that
doesn't necessarily help for partial implementations that might
support <stdint.h> but not all of C99.

This leaves open the question of which standard headers an
implementation may omit while still being conforming. Presumably we
don't want to allow "#ifinclude <stdio.h>" to fail for a conforming
hosted implementation.

Michal Nazarewicz

unread,
Apr 20, 2010, 5:28:33 PM4/20/10
to
> Michal Nazarewicz <min...@tlen.pl> writes:
>> Personally, I would go for something I think is more generic, which is
>> a "_Has" (or #has if you will) preprocessor operator, ie:
>>
>> #if _Has <stdatomic.h>
>> # include <stdatomic.h>
>> #else
>> # error This program requires stdatomic.h
>> #endif
>>
>> a shorthand #ifhas could be provided as well.
>>
>> This would be more generic in such a way that libraries not covered by
>> the standard could be checked as well, ie.:
>>
>> #ifhas <some-funky-library.h>
>> # include <some-funky-library.h>
>> #else
>> /* ... provide a simpler, inferior implementation ... */
>> #endif

Keith Thompson <ks...@mib.org> writes:
> I like it.
>
> For simplicity, I suggest that the _Has operator should specifically
> test whether the named header can be successfully #included, not
> whether a library exists. It could of course be applied to any
> headers, whether they're specified in the library or not.

Precisely.

> Since the most common use is going to be
>
> #if _Has <foo.h>
> #include <foo.h>
> ...
>
> I suggest a shorthand, something like:
>
> #ifinclude <foo.h>
> /* <foo.h> has been included */
> #else
> /* <foo.h> has not been included */
> #endif

That could be added *additionally* to the _Has operator but not replace
it though. In particular one could want to check if two different
headers exist prior to including them all so personally I would be happy
with just the _Has. :)

> This could be particularly useful for code that need to work across
> versions of the standard. For example, if C90 had had this feature,
> you could write:
>
> #ifinclude <stdint.h>
> #else
> typedef unsigned long uint32_t;
> /* Omitted code to check the actual size */
> #endif
>
> Yes, strictly speaking you could check __STD_VERSION__, but that
> doesn't necessarily help for partial implementations that might
> support <stdint.h> but not all of C99.

Exactly. I wanted to bring that example but didn't since C99 does not
have the _Has operator or your proposed #ifinclude.

> This leaves open the question of which standard headers an
> implementation may omit while still being conforming. Presumably we
> don't want to allow "#ifinclude <stdio.h>" to fail for a conforming
> hosted implementation.

It would bring the whole new area of jokes thou:

#if !_Has <stdio.h>
# error Your standard library is not very standard.

Seebs

unread,
Apr 20, 2010, 4:30:20 PM4/20/10
to
On 2010-04-20, Michal Nazarewicz <min...@tlen.pl> wrote:
> Can you point to some document that describes that? I don't see how
> this can be done. In particular one can do something like:

> #v+
> void foo(struct foo args) {
> struct foo *argsp = &args;
> }
> #v-

> which would imply that the structure would have to be placed in the
> memory. As such, I don't see how some of it's elements can be passed
> via registers.

The compiler would have to move things from registers into an object
when it got that far, same as it would for any other value passed
in a register.

Dag-Erling Smørgrav

unread,
Apr 20, 2010, 9:04:55 PM4/20/10
to
Michal Nazarewicz <min...@tlen.pl> writes:
> II *Named Arguments*
> [...]

Have you considered the full ramifications of this proposal?

Currently, argument names are optional in prototypes and are often left
out for a good reason: because they are in the same namespace as
identifiers and can collide with functions or variables declared in
other headers or in the source file that includes your header.

Furthermore, different implementations of the same API may use different
names for the same arguments. For instance, the standard names the
first two fprintf() / sprintf() arguments "stream" / "s" and "format".
FreeBSD's libc calls them "fp" / "str" and "fmt" (internally - the
prototype in <stdio.h> does not name them). The GNU C library calls
them __stream / __s and __format and *does* include the names in the
header.

I think named arguments is one of those things that sound really cool
until you actually start using them...

Before you say "other languages have them and they work fine", consider
that these are languages where namespaces are handled differently and
where named arguments were included in the initial design (Ada) and / or
are used only for optional arguments (Lisp), and languages for which, de
jure or de facto, there is only one implementation (Visual Basic, C#).

DES
--
Dag-Erling Smørgrav - d...@des.no

Michal Nazarewicz

unread,
Apr 20, 2010, 9:22:41 PM4/20/10
to
Dag-Erling Smørgrav <d...@des.no> writes:

> Michal Nazarewicz <min...@tlen.pl> writes:
>> II *Named Arguments*
>> [...]
>
> Have you considered the full ramifications of this proposal?
>
> Currently, argument names are optional in prototypes and are often left
> out for a good reason: because they are in the same namespace as
> identifiers and can collide with functions or variables declared in
> other headers or in the source file that includes your header.

I don't now how about namespace, but the have definitely *different*
*scope* thus they do not collide in any ways with file-scoped variables
or functions.

> Furthermore, different implementations of the same API may use different
> names for the same arguments.

The names (or lack of them thereof) would became the API.

Dag-Erling Smørgrav

unread,
Apr 20, 2010, 9:35:03 PM4/20/10
to
Michal Nazarewicz <min...@tlen.pl> writes:

> Dag-Erling Smørgrav <d...@des.no> writes:
> > Furthermore, different implementations of the same API may use
> > different names for the same arguments.
> The names (or lack of them thereof) would became the API.

In that case, named arguments will join the increasingly long list of
standard features which are universally or near-universally ignored by
vendors.

Dag-Erling Smørgrav

unread,
Apr 20, 2010, 9:36:52 PM4/20/10
to
Dag-Erling Smørgrav <d...@des.no> writes:

(assuming you meant that the argument names used in the standard will
become part of the API, so that all vendors will have to update their
implementations to use those exact names in their headers and resolve
any conflicts that arise)

Dag-Erling Smørgrav

unread,
Apr 20, 2010, 9:37:11 PM4/20/10
to

(assuming you meant that the argument names used in the standard will


become part of the API, so that all vendors will have to update their
implementations to use those exact names in their headers and resolve
any conflicts that arise)

DES

Wojtek Lerch

unread,
Apr 20, 2010, 11:00:19 PM4/20/10
to
"Michal Nazarewicz" <min...@tlen.pl> wrote in message
news:877ho1t...@erwin.mina86.com...

> Dag-Erling Smørgrav <d...@des.no> writes:
>
>> Currently, argument names are optional in prototypes and are often left
>> out for a good reason: because they are in the same namespace as
>> identifiers and can collide with functions or variables declared in
>> other headers or in the source file that includes your header.
>
> I don't now how about namespace, but the have definitely *different*
> *scope* thus they do not collide in any ways with file-scoped variables
> or functions.

They can collide with macros.

Michal Nazarewicz

unread,
Apr 21, 2010, 1:55:38 AM4/21/10
to
>> Dag-Erling Smørgrav <d...@des.no> writes:
>>> Furthermore, different implementations of the same API may use
>>> different names for the same arguments.

> Michal Nazarewicz <min...@tlen.pl> writes:
> > The names (or lack of them thereof) would became the API.

Dag-Erling Smørgrav <d...@des.no> writes:
> In that case, named arguments will join the increasingly long list of
> standard features which are universally or near-universally ignored by
> vendors.
>
> (assuming you meant that the argument names used in the standard will
> become part of the API, so that all vendors will have to update their
> implementations to use those exact names in their headers and resolve
> any conflicts that arise)

That's not the case. Names in existing functions won't magically became
named. They'll became named only through the use of a designated
syntax. So if a function author decides that some arguments should be
named then she will be able to do that.

Dag-Erling Smørgrav

unread,
Apr 21, 2010, 2:18:13 AM4/21/10
to
Michal Nazarewicz <min...@tlen.pl> writes:
> Dag-Erling Smørgrav <d...@des.no> writes:
> > Michal Nazarewicz <min...@tlen.pl> writes:
> > > The names (or lack of them thereof) would became the API.
> > In that case, named arguments will join the increasingly long list of
> > standard features which are universally or near-universally ignored by
> > vendors.
> >
> > (assuming you meant that the argument names used in the standard will
> > become part of the API, so that all vendors will have to update their
> > implementations to use those exact names in their headers and resolve
> > any conflicts that arise)
> That's not the case. Names in existing functions won't magically became
> named. They'll became named only through the use of a designated
> syntax. So if a function author decides that some arguments should be
> named then she will be able to do that.

Sorry, but either you're contradicting yourself or I've had way too
little sleep. Or both.

jacob navia

unread,
Apr 21, 2010, 11:09:12 AM4/21/10
to
Dag-Erling Smørgrav a écrit :

> Michal Nazarewicz <min...@tlen.pl> writes:
>> II *Named Arguments*
>> [...]
>
> Have you considered the full ramifications of this proposal?
>
> Currently, argument names are optional in prototypes and are often left
> out for a good reason: because they are in the same namespace as
> identifiers and can collide with functions or variables declared in
> other headers or in the source file that includes your header.
>

Excuse me but that is completely wrong. Identifiers within prototypes
have their own name space!

Proof:

void fn(int x);
void fn1(int x);

or even

void fn(int fn);

Compile those and you will see.

jacob navia

unread,
Apr 22, 2010, 4:30:52 AM4/22/10
to
Michal Nazarewicz a �crit :
>
> I *Default Function Argument*
>
> 1. The default value of a function's argument has proved to be useful
> in C++ programs as well as in other languages which has such
> a notion. It allows for more condensed function call in the usual
> cases still allowing for a configuration when required.
>
> 2. Syntax and semantics of such feature should be the same as in C++.
>
> 3. Example:
>
> #v+
> struct node {
> struct node *next;
> int key;
> const char *value;
> };
>
> struct void *get(struct node *first, int key, const char *def = NULL) {
> for (; first; first = first->next) {
> if (first->key == key)
> return first->value;
> return def;
> }
> #v-
>
> 4. In the current standard, such syntax it is invalid thus it will
> not affect existing code. Moreover, many C implementations are
> also capable of accepting C++ code thus implementing this feature
> would be an easy task in many such cases.
>
>

Much more needs to be specified.

The expression at the right side of the equals sign is necessarily a constant?

Within lcc-win it can be ANY expression.

It will be evaluated each time within the context of the function call.
Only global variables can be used. Local variables of the function can't be used.

jacob navia

unread,
Apr 22, 2010, 4:37:25 AM4/22/10
to
Michal Nazarewicz a écrit :
>
> VII *Function Overloading*
>
> 1. Function overloading is a feature that may help programmer
> concentrate on the general idea of the code he or she is
> developing without thinking too much about types that are being
> used.
>
> 2. Function declared in `math.h` are perfect example of such
> situation. Existence of functions such as `sin`, `sinf` and
> `sinl` force programmer to think about underlying type whereas it
> may not be that important.
>
> 3. The situation goes worse when one decides that a different type is
> to be used. In such situation, all calls to type-dependent
> functions have to be traced and replaced. This operation is
> rather boring and error-prone.
>
> 4. Situation gets even more complicated when one wants to develop
> a code where the type used is dependent on a macro definition or
> a typedef. This may be even more tricky if the macro/typedef
> comes from the external library and there's no clear way of
> telling what type it is during prepossessing stage.
>
> 5. All such situations would be trivial if function overloading was
> allowed.
>
> 6. To maximise compatibility with older implementations a syntax
> taken from C++ could be used for functions with external linkage:
>
> #v+
> extern "C++" float mysin(float x) { return sinf(x); }
> extern "C++" float mysin(double x) { return sin(x); }
> extern "C++" float mysin(long double x) { return sinl(x); }
> #v-
>
> and analogous syntax far functions with internal linkage:
>
> #v+
> static "C++" float mysin(float x) { return sinf(x); }
> static "C++" float mysin(double x) { return sin(x); }
> static "C++" float mysin(long double x) { return sinl(x); }
> #v-
>
> 7. In the current standard, function overloading is invalid thus it

> will not affect existing code. Moreover, many C implementations
> are also capable of accepting C++ code thus implementing this
> feature would be an easy task in many such cases.
>
>

lcc-win implements this feature with
float overloaded mysin(float x) ;
float overloaded mysin(double x);

and later

float overloaded mysin(float x) { return sinf(x);}
etc

It is an error if the prototype and the function definition do not
match, as always.

Note that "overloaded" is not a keyword. You can still write:
int overloaded = 42;

It is only a keyword marker, i.e. it will have significance only in the
global context, and only within a declaration at that position: immediately
before the function name.

jacob navia

unread,
Apr 22, 2010, 4:40:34 AM4/22/10
to
Michal Nazarewicz a écrit :
> X *Unnamed Arguments*
>
> 1. It sometimes happens that a function takes an argument but does
> not use it. This most common for callback functions or "virtual
> methods" when simulating object oriented programing.
>
> 2. At the same time, some implementations allow to turn diagnostics
> informing of unused variables on. Such diagnostics may help in
> identifying problems in the code.
>
> 3. However, when the two above combined, warnings about unused
> arguments are produced when it is user's intend no to use them.
> Common technique is to cast such an argument to void at the
> beginning of a function to silence the warning.
>
> 4. C++ allows for a name of an argument to be omitted in function
> definition which solves the above problem. The same could be
> implemented in C.
>
> 5. The current standard requires names to be present for all
> function's arguments in function definition so this change would
> not affect conforming code. At the same time, many
> C implementations are also capable of compiling C++ code thus
> implementing this feature could be easy and straightforward.
>
>

Lcc-win implements this feature.

Michal Nazarewicz

unread,
Apr 22, 2010, 4:45:16 AM4/22/10
to
> Michal Nazarewicz a écrit :

>> I *Default Function Argument*
>>
>> 1. The default value of a function's argument has proved to be useful
>> in C++ programs as well as in other languages which has such
>> a notion. It allows for more condensed function call in the usual
>> cases still allowing for a configuration when required.
>>
>> 2. Syntax and semantics of such feature should be the same as in C++.
>>
>> 3. Example:
>>
>> #v+
>> struct node {
>> struct node *next;
>> int key;
>> const char *value;
>> };
>>
>> struct void *get(struct node *first, int key, const char *def = NULL) {
>> for (; first; first = first->next) {
>> if (first->key == key)
>> return first->value;
>> return def;
>> }
>> #v-
>>
>> 4. In the current standard, such syntax it is invalid thus it will
>> not affect existing code. Moreover, many C implementations are
>> also capable of accepting C++ code thus implementing this feature
>> would be an easy task in many such cases.

jacob navia <ja...@nospam.org> writes:
> Much more needs to be specified.
>
> The expression at the right side of the equals sign is necessarily a constant?

I'll quote what I have written: "Syntax and semantics of such feature


should be the same as in C++."

> Within lcc-win it can be ANY expression.

I don't see this to be crucially. Sure, it would be nice, but constant
default arguments would already be a big step in my opinion.

Michal Nazarewicz

unread,
Apr 22, 2010, 4:51:42 AM4/22/10
to
jacob navia <ja...@nospam.org> writes:
> lcc-win implements this feature with
> float overloaded mysin(float x) ;
> float overloaded mysin(double x);
>
> and later
>
> float overloaded mysin(float x) { return sinf(x);}
> etc

I feel that using `extern "C++"` and `static "C++"` would be more
familiar for users who know C++. And in my opinion unification of C and
C++ syntax is also one of the things standard should go for -- sure
there will be differences but still if we can do something, why not?
(Like inclusion of "long long" in C++0X, inclusion of "inline" in C, and
probably some more.)

Michal Nazarewicz

unread,
Apr 22, 2010, 5:12:56 AM4/22/10
to
> Michal Nazarewicz <min...@tlen.pl> writes:
>> That's not the case. Names in existing functions won't magically became
>> named. They'll became named only through the use of a designated
>> syntax. So if a function author decides that some arguments should be
>> named then she will be able to do that.

Dag-Erling Smørgrav <d...@des.no> writes:
> Sorry, but either you're contradicting yourself or I've had way too
> little sleep. Or both.

The confusion may go from the fact that I use "named arguments" meaning
an arguments that can be passed to the function using the new syntax.
Arguments that have name in prototype in C90 or C99 are not, by this
definition, named.

For instance consider the code:

#v+
void foo(int); /* Argument has no name, it cannot be passed by name */
void foo(int x); /* The argument has a name but still, by the above
definition it is "unnamed" thus it cannot be passed
using named arguments syntax. */
void foo(int y); /* Perfectly valid. */
void bar(int x); /* Same as above */

foo(42); /* Valid */
foo(.x = 42); /* Invalid */
bar(.x = 42); /* Invalid *.

void baz(int .x); /* A named argument that when function is called must
be passed by name. */
void baz(int .y); /* Invalid, the two prototypes do not match. */

baz(42); /* Invalid, the first argument must be passed by
name */
baz(.x = 42); /* Valid */
#v-

jacob navia

unread,
Apr 22, 2010, 7:58:55 AM4/22/10
to
Michal Nazarewicz a écrit :

> jacob navia <ja...@nospam.org> writes:
>> lcc-win implements this feature with
>> float overloaded mysin(float x) ;
>> float overloaded mysin(double x);
>>
>> and later
>>
>> float overloaded mysin(float x) { return sinf(x);}
>> etc
>
> I feel that using `extern "C++"` and `static "C++"` would be more
> familiar for users who know C++. And in my opinion unification of C and
> C++ syntax is also one of the things standard should go for -- sure
> there will be differences but still if we can do something, why not?
> (Like inclusion of "long long" in C++0X, inclusion of "inline" in C, and
> probably some more.)
>

extern C++ would replace the "overloaded" marker?

Or it means that I can use the STL just with

extern "C++" { /* here I program in C++ */ }

The problem is that you are supposing that there are no C compilers, just C++ compilers that do C if
needed.

Michal Nazarewicz

unread,
Apr 22, 2010, 8:15:05 AM4/22/10
to
> Michal Nazarewicz a écrit :
>> jacob navia <ja...@nospam.org> writes:
>>> lcc-win implements this feature with
>>> float overloaded mysin(float x) ;
>>> float overloaded mysin(double x);
>>>
>>> and later
>>>
>>> float overloaded mysin(float x) { return sinf(x);}
>>> etc
>>
>> I feel that using `extern "C++"` and `static "C++"` would be more
>> familiar for users who know C++. And in my opinion unification of C and
>> C++ syntax is also one of the things standard should go for -- sure
>> there will be differences but still if we can do something, why not?
>> (Like inclusion of "long long" in C++0X, inclusion of "inline" in C, and
>> probably some more.)
>>

jacob navia <ja...@nospam.org> writes:
> extern C++ would replace the "overloaded" marker?

Yes.

> Or it means that I can use the STL just with
>
> extern "C++" { /* here I program in C++ */ }

No, that's not my intend. What could be possible though is:

#v+
extern "C++" {
float mysin(float x):
double mysin(double x);
}
#v-

so one wouldn't have to put the marker in front of every function but
something like:

#v+
extern "C++" {
template<class T> struct Foo { /* ... */ };
}
#v-

would *not* be allowed.


The intend is also that you could create a header like:

#v+
#ifndef __cplusplus
extern "C++" {
#endif

float mysin(float x):
double mysin(double x);

#ifndef __cplusplus
extern "C++" {
#endif
#v-

and then use it in both C code and C++ code.


It would be even better if C1X and C++1X committees cooperated on this
one and made `extern "C++"` an no-op in C++ and `extern "C"` an no-op in
C. This way, one could just write:

#v+
extern "C" float sinf(float x);
extern "C" double sin(double x);
extern "C++" float mysin(float x);
extern "C++" double mysin(double x);
#v-

and it'll be valid in both C and C++.

jacob navia

unread,
Apr 22, 2010, 8:15:20 AM4/22/10
to
Michal Nazarewicz a écrit :
>
> I'll quote what I have written: "Syntax and semantics of such feature
> should be the same as in C++."


This is completely wrong.

For instance in C++ you can write
void f(int , int );
void f(int , int = 7);

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf
8.3.6 Default arguments, page 161

In my implementation this is an error.


The problem is, and that is one of the bugs of C++, that you do not know if that is an error (i.e.
an inconsistency between two declarations), or if it is the intended behavior.

In C we have no "culture of automatic overloading", and a C programmer expects inconsistency to be
caught by the compiler.

The proposal of lcc-win stays within the semantics of the C language. I feel that all your
proposals could be implemented like this:

extern "C++" { /* here I program in C++ */ }

and that was it.

C is not C++, and if we adapt features of C++ they should stay within the C framework and not just
be imported as such.

The same happens with the "overloaded" functions proposal. I decided to put a MARKER (i.e. the
identifier "overloaded") to make any overloading EXPLICIT.

Implicit overloading like C++ is terrible and bad software engineering. It makes it very difficult
to catch inconsistencies between function declarations. EXPLICIT overloading is OK since the
programmer has to EXPLICITELY ALLOW a feature for it to be used.

Michal Nazarewicz

unread,
Apr 22, 2010, 9:28:33 AM4/22/10
to
> Michal Nazarewicz a écrit :
>>
>> I'll quote what I have written: "Syntax and semantics of such feature
>> should be the same as in C++."

jacob navia <ja...@nospam.org> writes:
> This is completely wrong.
>
> For instance in C++ you can write
> void f(int , int );
> void f(int , int = 7);

Haven't thought about that and yes, this may seem confusing so this
could be considered an error in C. I would be fine either way.

ld

unread,
Apr 23, 2010, 4:36:27 AM4/23/10
to
On Apr 18, 11:00 pm, Michal Nazarewicz <min...@tlen.pl> wrote:
> Hello everyone,
>
> As the committee gathered to discuss how the new C standard will look
> like I did some thinking of my own.  I thought about features that
> I would love to see in C.  I even collected thoughts of my twisted mind
> and condensed them into a text file.
>
> What is outrageous is that since I believe information and ideas want to
> be free and shared I have decided to post my concepts on the net instead
> of imprisoning them in my wicked brain.
>
> Maybe someone will find it useful somehow.  Maybe even some committee
> member will read those and bring them out on next meeting.  In any case,
> feel free to ignore this thread. :)
>
> (BTW. An HTML version of this post can be found at the following
> address: <URL:http://mina86.com/2010/04/18/new-c-features-proposal/>.)
>

Most of your proposal makes sense to me since I am developing Object
Oriented programming in C for a while now (about 10 years). The three
proposals that I made some time ago was anonymous structure, implicit
cast and overloading (extended as below) for the same reasons as
yours, but without much success. It is quite hard (and expansive) to
make new proposal to the standard from my country (France). So good
luck, but I strongly support your proposals which would make OOP in C
much easier and clean.

> VII *Function Overloading*
>
>  1. Function overloading is a feature that may help programmer
>     concentrate on the general idea of the code he or she is
>     developing without thinking too much about types that are being
>     used.
>
>  2. Function declared in `math.h` are perfect example of such
>     situation.  Existence of functions such as `sin`, `sinf` and
>     `sinl` force programmer to think about underlying type whereas it
>     may not be that important.
>
>  3. The situation goes worse when one decides that a different type is
>     to be used.  In such situation, all calls to type-dependent
>     functions have to be traced and replaced.  This operation is
>     rather boring and error-prone.
>
>  4. Situation gets even more complicated when one wants to develop
>     a code where the type used is dependent on a macro definition or
>     a typedef.  This may be even more tricky if the macro/typedef
>     comes from the external library and there's no clear way of
>     telling what type it is during prepossessing stage.
>
>  5. All such situations would be trivial if function overloading was
>     allowed.
>
>  6. To maximise compatibility with older implementations a syntax
>     taken from C++ could be used for functions with external linkage:
>

>     #v+


>     extern "C++" float mysin(float x) { return sinf(x); }
>     extern "C++" float mysin(double x) { return sin(x); }
>     extern "C++" float mysin(long double x) { return sinl(x); }
>     #v-
>
>     and analogous syntax far functions with internal linkage:
>
>     #v+
>     static "C++" float mysin(float x) { return sinf(x); }
>     static "C++" float mysin(double x) { return sin(x); }
>     static "C++" float mysin(long double x) { return sinl(x); }
>     #v-
>

>  7. In the current standard, function overloading is invalid thus it


>     will not affect existing code.  Moreover, many C implementations
>     are also capable of accepting C++ code thus implementing this
>     feature would be an easy task in many such cases.

In this particular case, I would also add the reserved keyword
_Operator to defined an alias for the C operators:

#v+
static "C++" vector _Operator + (vector x, vector y) { return
vector_add(x,y); }
static "C++" vector _Operator - (vector x, vector y) { return
vector_sub(x,y); }
static "C++" vector _Operator * (vector x, vector y) { return
vector_mul(x,y); }
static "C++" vector _Operator / (vector x, vector y) { return
vector_div(x,y); }

static "C++" vector _Operator * (vector x, double s) { return
vector_scl(x,s); }
#v-

I would also make a strong statement that static (internal linkage)
does not require function name mangling while extern (external
linkage) requires C++ compatible function name mangling. What is
really useful for C programmers is the static version since the
function called can be declared extern. So

extern "C++" vector _Operator + (vector x, vector y) { return
vector_add(x,y); }

could either uses C++ function name mangling (C++ way) or be
equivalent to (C way)

extern "C" vector vector_add(vector x, vector y);
static "C++" vector _Operator + (vector x, vector y) { return
vector_add(x,y); }

Maybe some clarification on this point would be welcome since the
former could afraid C compiler implementors and users (linkage
compatibility problem).

Regards,

Laurent.

Michal Nazarewicz

unread,
Apr 24, 2010, 5:33:07 AM4/24/10
to
ld <laurent...@gmail.com> writes:
> It is quite hard (and expansive) to make new proposal to the standard
> from my country (France). So good luck, but I strongly support your
> proposals which would make OOP in C much easier and clean.

I didn't really planed on pursuing the matter much further. I couldn't
find any Polish member of ISO who could be interested in C working group
and I don't really think I have much resources to push the proposal
further.

Anyway, since I wrote the document I just thought I'd share my ideas.

> On Apr 18, 11:00 pm, Michal Nazarewicz <min...@tlen.pl> wrote:

>> VII *Function Overloading*

> In this particular case, I would also add the reserved keyword
> _Operator to defined an alias for the C operators:
> #v+
> static "C++" vector _Operator + (vector x, vector y) { return
> vector_add(x,y); }
> static "C++" vector _Operator - (vector x, vector y) { return
> vector_sub(x,y); }
> static "C++" vector _Operator * (vector x, vector y) { return
> vector_mul(x,y); }
> static "C++" vector _Operator / (vector x, vector y) { return
> vector_div(x,y); }
>
> static "C++" vector _Operator * (vector x, double s) { return
> vector_scl(x,s); }
> #v-

As of operators overloading I have another batch of thoughts. In
particular, I would like to see this set of rules:

1. If != operator is not found, compiler changes expression from `a !=
b` to `b != a` and tries again; if this fails, compiler undos the
change and proceeds to the next rule.
2. If an != operator is not found, compiler transforms expression from
`a != b` to `!(a == b)` and tries to look for ==.
3. If an == operator is not found, compiler transforms expression from
`a == b` to `b == a` and tries again; this rule only applies once.

4. If >, <= or >= operator is not found, compiler translates `a # b`
into `b < a`, `!(b < a)` or `!(a < b)` and tries to look for <.

5. If a post increment (post decrement) operator is not found, compiler
changes the expression from `a##` to (pseudo code) `typeof(a) __temp
= a, ##a, __temp` and tries to look for pre increment (pre
decrement).
6. If pre increment (pre decrement) operator is not found compiler
translates expression from `++a` (`--a`) to `a += 1` (`a -= 1`) and
tries to look for the plus-equal (mines-equal) operator.

7. If + or * binary operator is not found, compiler changes expression
from `a # b` to `b # a` and tries again; if this fails, compiler
undos the change and proceeds to the next rule.
8. If binary operator # that has a #= variant is not found, compiler
translates expression from `a # b` to (pseudo code) `typeof(a)
__temp = a, __temp #= b` and tries to look for #=.
9. If, after performing the previous rule += or *= operator is not
found, compiler changes expression (pseudo code) `typeof(a)
__temp = a, __temp #= b` to (pseudo code) `typeof(b)
__temp = b, __temp #= a` and tries again.

10. If an [] operator is not found, compiler translates the expression
from `a[b]` to `*(a + b)`.
11. If an -> operator is not found, compiler translates the expression
from `a->b` to `(*a).b`.

Or even, the standard cold forbid overloading of the derived operators.
I believe this would simplify operator overloading a great deal.

Also, I don't consider overloading of comma is such a great idea.

> I would also make a strong statement that static (internal linkage)
> does not require function name mangling while extern (external
> linkage) requires C++ compatible function name mangling.

Yes, that's my intention. Of course, I wouldn't be too demandful and
not impose any particular mangling method and in the end would not force
it to work with all possible C++ compilers. In particular, code
compiled with gcc would link with code compiled with g++ but not with MS
VC++.

David R Tribble

unread,
Apr 24, 2010, 2:14:45 PM4/24/10
to
Michal Nazarewicz wrote:
> I thought about features that I would love to see in C.
>
> I *Default Function Argument*
> 1. The default value of a function's argument has proved to be useful
> in C++ programs as well as in other languages which has such
> a notion. It allows for more condensed function call in the usual
> cases still allowing for a configuration when required.

FWIW, this capability can be supplied by the more general feature
of my proposed "function aliases", which provide a rudimentary,
but powerful, function overloading facility for C. The proposal is at:

http://david.tribble.com/text/c0xalias.htm

Consider your example:

> struct void *get(struct node *first, int key, const char *def = NULL)

> { ... }

This could be done using function aliases like this:

struct node * get3(struct node *first, int key, const char *def)
{
// (as per your example
}

struct node * get2(struct node *first, int key)
{
return get3(first, key, NULL); // 3rd arg defaulted
}

alias struct node * get(struct node *first, int key, const char
*def)
= get3;
alias struct node * get(struct node *first, int key)
= get2;

Calls to get() are then equivalent to (replaced with) calls to either
get2() or get3():

p = get(f, k, "abc"); // => get3(f, k, "abc");
p = get(f, k); // => get2(f, k);

Function aliases do not require any changes to the C linker model.

-drt

Michal Nazarewicz

unread,
Apr 24, 2010, 6:02:07 PM4/24/10
to
> Michal Nazarewicz wrote:
>> I thought about features that I would love to see in C.
>>
>> I *Default Function Argument*
>> 1. The default value of a function's argument has proved to be useful
>> in C++ programs as well as in other languages which has such
>> a notion. It allows for more condensed function call in the usual
>> cases still allowing for a configuration when required.

David R Tribble <da...@tribble.com> writes:
> FWIW, this capability can be supplied by the more general feature
> of my proposed "function aliases", which provide a rudimentary,
> but powerful, function overloading facility for C. The proposal is at:
>
> http://david.tribble.com/text/c0xalias.htm
>
> Consider your example:
>
>> struct void *get(struct node *first, int key, const char *def = NULL)
>> { ... }
>
> This could be done using function aliases like this:
>
> struct node * get3(struct node *first, int key, const char *def)
> {
> // (as per your example
> }
>
> struct node * get2(struct node *first, int key)
> {
> return get3(first, key, NULL); // 3rd arg defaulted
> }
>
> alias struct node * get(struct node *first, int key, const char
> *def)
> = get3;
> alias struct node * get(struct node *first, int key)
> = get2;
>
> Calls to get() are then equivalent to (replaced with) calls to either
> get2() or get3():
>
> p = get(f, k, "abc"); // => get3(f, k, "abc");
> p = get(f, k); // => get2(f, k);
>
> Function aliases do not require any changes to the C linker model.

I don't like that. Using such aliases to implement default arguments is
just cumbersome. This reminds me of Java where overloading is allowed
but default arguments not -- you end up adding bunch of functions just
to implement what you could do using a trivial syntax.

And honestly, I'd prefer to have function overloading and when we have
that I do net see the point of aliases. I mean it's a syntax sugar but
IMO not worth the effort.

In my opinion, the biggest use of aliases could come from actually
creating another symbol which aliases the first one during linkage but
if I understood correctly, your intend was for aliases to be fully
resolved during compilation and gone by the time a translation unit is
compiled.

William Ahern

unread,
Apr 24, 2010, 7:25:24 PM4/24/10
to
[do not have Tribble's article to reply directly to]

Michal Nazarewicz <min...@tlen.pl> wrote:
<snip>


> David R Tribble <da...@tribble.com> writes:
> > FWIW, this capability can be supplied by the more general feature
> > of my proposed "function aliases", which provide a rudimentary,
> > but powerful, function overloading facility for C. The proposal is at:
> >
> > http://david.tribble.com/text/c0xalias.htm
> >
> > Consider your example:
> >
> >> struct void *get(struct node *first, int key, const char *def = NULL)
> >> { ... }
> >
> > This could be done using function aliases like this:
> >
> > struct node * get3(struct node *first, int key, const char *def)
> > {
> > // (as per your example
> > }
> >
> > struct node * get2(struct node *first, int key)
> > {
> > return get3(first, key, NULL); // 3rd arg defaulted
> > }
> >
> > alias struct node * get(struct node *first, int key, const char
> > *def)
> > = get3;
> > alias struct node * get(struct node *first, int key)
> > = get2;
> >
> > Calls to get() are then equivalent to (replaced with) calls to either
> > get2() or get3():
> >
> > p = get(f, k, "abc"); // => get3(f, k, "abc");
> > p = get(f, k); // => get2(f, k);

<snip>

That _particular_ use of function aliasing/overloading can be accomplished
with C99 today. To wit:

#define PP_NARG_(a, b, c, d, N, ...) N
#define PP_NARG(...) PP_NARG_(__VA_ARGS__, 4, 3, 2, 1, 0)
#define PP_CALL(F, ...) F(__VA_ARGS__)
#define PP_PASTE(x, y) x ## y
#define PP_XPASTE(x, y) PP_PASTE(x, y)

struct node *get3(struct node *first, int key, const char *def);
struct node *get2(struct node *first, int key);

#define get(...) PP_CALL(PP_XPASTE(get, PP_NARG(__VA_ARGS__)), __VA_ARGS__)

There's a simpler way to accomplish this when--as above--you're really just
appending default arguments.

#define get3(a, b, c, ...) get3((a), (b), (c))
#define get(...) get3(__VA_ARGS__, 0)

True, this all fails when you want to overload based on argument or result
type, and not on number. Just thought I'd throw that out there, though.

David R Tribble

unread,
Apr 25, 2010, 11:11:52 PM4/25/10
to
Michal Nazarewicz wrote:
>> I thought about features that I would love to see in C.
>>
>> I *Default Function Argument*
>> 1. The default value of a function's argument has proved to be useful
>> in C++ programs as well as in other languages which has such
>> a notion. It allows for more condensed function call in the usual
>> cases still allowing for a configuration when required.
>

David R Tribble writes:
>> FWIW, this capability can be supplied by the more general feature
>> of my proposed "function aliases", which provide a rudimentary,
>> but powerful, function overloading facility for C. The proposal is at:
>> http://david.tribble.com/text/c0xalias.htm
>>
>> Consider your example:

>> [...]


>>
>> This could be done using function aliases like this:

>> [...]


>>
>> Function aliases do not require any changes to the C linker model.
>

Michal Nazarewicz wrote:
> I don't like that. Using such aliases to implement default arguments is
> just cumbersome. This reminds me of Java where overloading is allowed
> but default arguments not -- you end up adding bunch of functions just
> to implement what you could do using a trivial syntax.
>
> And honestly, I'd prefer to have function overloading and when we have
> that I do net see the point of aliases. I mean it's a syntax sugar but
> IMO not worth the effort.

Adding true function overloading to C involves more than syntactic
sugar; it requires a fundamental change to the C linkage model.
This fact alone is enough to kill such a proposal dead in its
tracks.

My function aliases proposal avoids all that.


> In my opinion, the biggest use of aliases could come from actually
> creating another symbol which aliases the first one during linkage but
> if I understood correctly, your intend was for aliases to be fully
> resolved during compilation and gone by the time a translation unit is
> compiled.

Exactly. Therefore no change to the linkage model is required,
and all actual function names remain as they are in the current
model.

-drt

Ian Collins

unread,
Apr 25, 2010, 11:29:57 PM4/25/10
to

Neither would default parameters. The default value will be inserted by
the compiler.

--
Ian Collins

jacob navia

unread,
Apr 26, 2010, 3:41:41 AM4/26/10
to
David R Tribble a �crit :

> Adding true function overloading to C involves more than syntactic
> sugar; it requires a fundamental change to the C linkage model.
> This fact alone is enough to kill such a proposal dead in its
> tracks.
>
> My function aliases proposal avoids all that.

I have implemented function overloading in my compiler system lcc-win.
Can you tell me why you think that the linkage model needs to be changed?

Thanks

Ian Collins

unread,
Apr 26, 2010, 5:13:29 AM4/26/10
to
On 04/26/10 07:41 PM, jacob navia wrote:
> David R Tribble a écrit :

Mangled names?

--
Ian Collins

jacob navia

unread,
Apr 26, 2010, 7:21:21 AM4/26/10
to
Ian Collins a écrit :

Yes, and so what?

In what do "mangled" names affect anything?

lcc-win generates name with the function name, followed by the types of
each argument.

And how do those names affect anything?

I still do not see why there could be a problem

Francis Glassborow

unread,
Apr 26, 2010, 8:24:26 AM4/26/10
to
jacob navia wrote:
> Ian Collins a �crit :

>> On 04/26/10 07:41 PM, jacob navia wrote:
>>> David R Tribble a �crit :

>>>
>>>> Adding true function overloading to C involves more than syntactic
>>>> sugar; it requires a fundamental change to the C linkage model.
>>>> This fact alone is enough to kill such a proposal dead in its
>>>> tracks.
>>>>
>>>> My function aliases proposal avoids all that.
>>>
>>> I have implemented function overloading in my compiler system lcc-win.
>>> Can you tell me why you think that the linkage model needs to be
>>> changed?
>>
>> Mangled names?
>>
>
> Yes, and so what?
>
> In what do "mangled" names affect anything?
>
> lcc-win generates name with the function name, followed by the types of
> each argument.
>
> And how do those names affect anything?
>
> I still do not see why there could be a problem

They change the linkage model slightly and generate long names that some
primitive linkers cannot handle. That is why I prefer some form of
aliasing facility (though mine is a little different to David's as I
prefer to see the entire overload set declared in a single block:

overload foo {
int bar1(int, float);
void bar2(void);
float bar3(double, float);
}

And so there is no risk of accidental/unexpected overloading. I would
also allow those to be declarations of the functions. No name mangling
required, complete overload set explicitly visible and the compiler can
check if any of the proposed overloads would conflict.

Work would need to be done defining best matches unless we decided that
only exact matches were to be allowed in this context.

jacob navia

unread,
Apr 26, 2010, 8:32:32 AM4/26/10
to
Francis Glassborow a écrit :

> They change the linkage model slightly and generate long names that some
> primitive linkers cannot handle.

C99 sets the required minimum name length that must be supported
at 255 if memory serves...

The possibility of those linkers still around when the new C standard
is published is almost zero. Anyway, if those environments need a linker
with 6 characters maximum, you can always make a table like this:

ThisIsALongNameThatExceeds255CharsWhenRepeated AAAAA1
ThisIsAnotherlongishNameThatIHaveToFigureOutForThisExample AAAAA2

and use those names to link...

You have place for a symbol table of a million entries with that.

I do not see why all sane environments must suffer because of the possibility of some broken linker
exists somewhere.

Thomas David Rivers

unread,
Apr 26, 2010, 9:21:15 AM4/26/10
to
jacob navia wrote:
>
> I do not see why all sane environments must suffer because of the
> possibility of some broken linker exists somewhere.

The z/OS linker continues to be widely used. While the
new "binder" does support longer names; many other requirements
continue to force programmers to use the older-style
module formats that restrict names to 8 characters.

This "broken linker" remains the core of continued development
for many fortune-500 companies, and the largest banks in the
world.

Your table approach for mapping long names to short ones
is the typical solution, but we continue to have customers
that prefer to not do that, and restrict themselves to
8-character or less symbol names (all upper-case as well.)

I mention this only because it's an example of something
that doesn't just exist 'somewhere' - but something
that remains vitally important to computing around the
world.

Having said all of that, I can say that I'm not too fond
of the restriction; but sometimes I don't enjoy gravity
either.. gotta live with both.

- Dave Rivers -

--
riv...@dignus.com Work: (919) 676-0847
Get your mainframe programming tools at http://www.dignus.com

Michal Nazarewicz

unread,
Apr 26, 2010, 9:50:45 AM4/26/10
to
David R Tribble <da...@tribble.com> writes:
> Adding true function overloading to C involves more than syntactic
> sugar; it requires a fundamental change to the C linkage model.

I'm aware it's not just a trivial syntactic sugar, but it's not such
a big change to linker model either. As a matter of fact, there will be
no change to linker since it will still operate on identifiers and the
fact the names were mangled by the compiler shouldn't bother the linker.

> This fact alone is enough to kill such a proposal dead in its
> tracks.
>
> My function aliases proposal avoids all that.

One of the goals set by the committee is to try and maintain
compatibility with C++ and as such I think if it is possible to use
a feature from C++ it should be done instead of creating own syntax
(yes, we probably won't see templates in C any time soon but why not
function overloading and default arguments).

What I mean is that if there were no C++ we could try to invent some
better syntax then the trivial function overloading but in current
situation the C++ function overloading is, in my opinion, "good
enough".

Still, I do not agree that function overloading or aliases are good way
of implementing default arguments -- this is way too cumbersome. To
this day I don't understand why they didn't include that functionality,
that can be implemented purely in the compiler, in Java.

>> In my opinion, the biggest use of aliases could come from actually
>> creating another symbol which aliases the first one during linkage but
>> if I understood correctly, your intend was for aliases to be fully
>> resolved during compilation and gone by the time a translation unit is
>> compiled.
>
> Exactly. Therefore no change to the linkage model is required,
> and all actual function names remain as they are in the current
> model.

Again, linkage model won't be changed -- only names will get mangled by
the compiler so no changes in linker are required.

jacob navia

unread,
Apr 26, 2010, 12:02:05 PM4/26/10
to
Thomas David Rivers a écrit :

I proposed several solutions for your problem:

(1) Use the current linker proposed by IBM: the binder. This linker
has no name length problems.

OK You do not want to use the linker that works.

(2) Use a table approach, as I described in my last message.

OK You do not want to use a table either.

(3) You allow only the old z/OS linker with 8 character restrictions.
Note that many C99 functions like "feraiseexcept" (13 chars)
or "strtoimax" (9 chars) "nextafter" (9 chars) can't run unmodified
and have the SAME problem as mangled functions. Note that the standard
*requires* 63 significant characters in an identifier (not 255 as I posted
earlier, but surely more than 8)

The solution here is that all names are mangled by the compiler, and
make to fit into 8 characters, all uppercase. This is surely the case
TODAY already since IBM supports C99.

I think you are making a problem where there is none.
I am sure IBM and the compiler vendors have ALREADY a solution for this
problem, if not their system would just not run.

Thomas David Rivers

unread,
Apr 26, 2010, 3:02:36 PM4/26/10
to
jacob navia wrote:

>
> I proposed several solutions for your problem:
>
> (1) Use the current linker proposed by IBM: the binder. This linker
> has no name length problems.
>
> OK You do not want to use the linker that works.

Unfortunately - there are situations where the OS requires
you to use the old linker and the old executable format.
There still remain situations where the new-style load module
formats cannot be used. So, if you are developing a program
that requires that environment, the old limitations remain.
(e.g. I don't believe a PDSE can be part of the LINKLST.)

>
> (2) Use a table approach, as I described in my last message.
>
> OK You do not want to use a table either.
>
> (3) You allow only the old z/OS linker with 8 character restrictions.
> Note that many C99 functions like "feraiseexcept" (13 chars)
> or "strtoimax" (9 chars) "nextafter" (9 chars) can't run unmodified
> and have the SAME problem as mangled functions. Note that the standard
> *requires* 63 significant characters in an identifier (not 255 as I
> posted
> earlier, but surely more than 8)

Except - I believe that if you truncate all of those names at 8
characters; they remain unique? Is that not true?

And - I thought those that come from <fenv.h> are not required
to be implemented (Appendix F?) Recall, this machine does not
(necessarily) use IEEE floating pt. So, if I'm not mistaken,
many of those longer "newer" names are not required for a C99
implementation? (Annex F of the C99 standard indicates that
you only need those "long name" functions if you define the macro
__STDC_IEC_559__.)

Oh - I believe you are mistaken, the standard requires
63 characters for internal linkage. External linkage
only requires 31 characters (see section 5.2.4.1. entitled
"Translation Limits") I'm assuming we are including
the ability to invoke functions with external linkage?

>
> The solution here is that all names are mangled by the compiler, and
> make to fit into 8 characters, all uppercase. This is surely the case
> TODAY already since IBM supports C99.

Yes - IBM does support C99 - but not in the environments I'm
describing.

The IBM C99 environment is "Language Environment" which can cover
many of the situations, but not all of the program environments
available on a mainframe.

And, the existence of our C offering, and the fact that people
take advantage of it, indicates there are some people that continue
to have this requirement.

And.. I can attest that several of our customers do not appreciate
the name-mangling/renaming approaches... as it happens, such renaming
makes it difficult to debug and to adopt the IBM standard mechanisms
for applying system maintenance (SMP/E). Some of our customers don't
even like lower-case letters in their symbols.

One can make the claim that that portion of the possible set of
users doesn't matter; but I don't think you can make the claim
that it doesn't exist.

That's all I'm after...


>
> I think you are making a problem where there is none.
> I am sure IBM and the compiler vendors have ALREADY a solution for this
> problem, if not their system would just not run.

We are a compiler vendor for that system. And, we do have
solutions.. one of them is to limit names to 8 characters.
Another is to use our pre-linker which adopts methods
similar to the one you suggest.

All I'm saying is that the statement:

"I do not see why all sane environments must suffer because
of the possibility of some broken linker exists somewhere."

needs to be considered with some caution, as there *are* "broken
linkers" that exist, and those environments continue to be
important. I cite this situation (with which we happen to be
very familiar) as an exemplar of such a fairly draconian environment.
And, I would hazard a guess, because of that example, that similar
environments, with similar limitations might exist. To dismiss
these as "not sane" might be unwise, or perhaps ill-informed.

The name length of external identifiers in C99 is 31 characters.
So, I would be willing to concede that the environment I'm speaking of
is, definitionally, not ANSI C99; and therefor can be dismissed.
(As an aside, I do point out that we can get pretty close even with
the limitation of 8 within the confines of the C99 library, I believe
all the required C99 functions happen to unique in the first 8
characters... but, I might be wrong on that. The limitation does
mean the programmer has to be very careful.)

Even so, the limit of 31 characters remains a pretty significant
restriction when you start tacking on various name-mangling approaches
(ala C++) for function overloading. Should some such approach
be considered, I would suggest this limit would need to be
dramatically increased. Our experience in C++ implementations
would tend to point to a number like 1024, or even larger.
But, I have no data on that; it's just a guess.

jacob navia

unread,
Apr 26, 2010, 3:50:17 PM4/26/10
to
Thanks for your very informative message Mr Rivers.

I see that the difficulties you are facing are quite real, and I
remember the IBM mainframe environment very well... it is a hard
environment to work in, and specially if you get out of COBOL+CICS.

Now, consider this program:

extern void nextafte(void);

#include <math.h>

int main(void)
{
nextafte();
double m = nextafter(2.3);
return 0;
}

This program must run since it is a fully conforming program. You can't
just cut at 8 positions, a name mangling schema must exist anyway.


Another possibility is to device a name mangling schema with less
footprint than the one I use in the windows implementation of lcc-win.
The original function name can be truncated at 4 chars, leaving 4 to
encode the different arguments. If there are (say) 4 overloaded versions
only, leaving the last char as '1' , '2', '3' and '4' will do and the
functions are still recognizable in the debugger.

Of course this is easier to say than to program, I know.

But this problem is transient, I am sure your customers will be using
the new linker until we get the committee to add overloaded functions to C.


:-)

Michal Nazarewicz

unread,
Apr 26, 2010, 5:09:01 PM4/26/10
to
> jacob navia wrote:
>> I proposed several solutions for your problem:
>>
>> (1) Use the current linker proposed by IBM: the binder. This linker
>> has no name length problems.
>>
>> OK You do not want to use the linker that works.

Thomas David Rivers <riv...@dignus.com> writes:
> Unfortunately - there are situations where the OS requires
> you to use the old linker and the old executable format.
> There still remain situations where the new-style load module
> formats cannot be used. So, if you are developing a program
> that requires that environment, the old limitations remain.
> (e.g. I don't believe a PDSE can be part of the LINKLST.)

If I understand it correctly, the environment does not support limits
required by C99 so there's no sweat -- not supporting C1X won't break
anything any further then not supporting C99 does.

I mean, since you have to apply workarounds anyway then adding mangling
won't change anything -- you'll still need to apply workarounds and no
one forces you to use function overloading.

Ian Collins

unread,
Apr 26, 2010, 5:21:16 PM4/26/10
to
On 04/26/10 11:21 PM, jacob navia wrote:
> Ian Collins a �crit :
>> On 04/26/10 07:41 PM, jacob navia wrote:
>>> David R Tribble a �crit :

>>>
>>>> Adding true function overloading to C involves more than syntactic
>>>> sugar; it requires a fundamental change to the C linkage model.
>>>> This fact alone is enough to kill such a proposal dead in its
>>>> tracks.
>>>>
>>>> My function aliases proposal avoids all that.
>>>
>>> I have implemented function overloading in my compiler system lcc-win.
>>> Can you tell me why you think that the linkage model needs to be
>>> changed?
>>
>> Mangled names?
>
> Yes, and so what?
>
> In what do "mangled" names affect anything?

Along with the issues with long names, any form of mangling will have to
be standardised and a means of linking with earlier libraries introduced.

> lcc-win generates name with the function name, followed by the types of
> each argument.

For all function, or just overloads?

--
Ian Collins

jacob navia

unread,
Apr 26, 2010, 5:25:08 PM4/26/10
to
Ian Collins a écrit :

>
> Along with the issues with long names, any form of mangling will have to
> be standardised and a means of linking with earlier libraries introduced.
>
Yes.

>> lcc-win generates name with the function name, followed by the types of
>> each argument.
>
> For all function, or just overloads?
>

For all overloaded functions. It preceeds the name with __ to avoid
the user name space. A similar schema is used for operator overloading

Ian Collins

unread,
Apr 26, 2010, 5:29:22 PM4/26/10
to

So if you overload f(int) with f(double), do you get two mangled names?

I can see that causing all sorts of problems with code using the
original function.

--
Ian Collins

Michal Nazarewicz

unread,
Apr 26, 2010, 5:44:31 PM4/26/10
to
Ian Collins <ian-...@hotmail.com> writes:
> Along with the issues with long names, any form of mangling will have
> to be standardised

C++ does not standardised mangling and everyone seem happy. ;)

> and a means of linking with earlier libraries introduced.

This is why I proposed `extern "C++"`. "Normal" functions won't get
mangled and thus compatibility with old code and libraries will be
preserved. Mangling will take place only when you explicitly request
it.

Ian Collins

unread,
Apr 26, 2010, 5:52:15 PM4/26/10
to
On 04/27/10 09:44 AM, Michal Nazarewicz wrote:
> Ian Collins<ian-...@hotmail.com> writes:
>> Along with the issues with long names, any form of mangling will have
>> to be standardised
>
> C++ does not standardised mangling and everyone seem happy. ;)

Not really, the lack of standardised name mangling is, to be blunt, a
pain in the arse. The only way to link code produced by different
compilers is through C linkage functions. I'd hate to see the same
problems in C.

>> and a means of linking with earlier libraries introduced.
>
> This is why I proposed `extern "C++"`. "Normal" functions won't get
> mangled and thus compatibility with old code and libraries will be
> preserved. Mangling will take place only when you explicitly request
> it.

For that to work, C++ linkage would have to be standardised, which it isn't.

--
Ian Collins

jacob navia

unread,
Apr 26, 2010, 5:58:54 PM4/26/10
to
Ian Collins a écrit :

Either:

(1) You want the overloading of standard C In that case do not do anything!
(2) You want to have two different functions for f: one with an integer argument
and one with double argument. You overload them and you write your two functions.
When the compiler sees
f(76);
it sees an overloaded function name, looks up and finds that f(int) matches. In the first
pass, it does NO promotions, so it finds f(int). Then, we are done.

Problems arise when you pass it a long double:
f(76.7L);
In the first pass without promotions it finds none. In the second pass it finds
two possible functions: f(int) and f(double). This is an ambiguous call.
It complains and compilation fails.

Keith Thompson

unread,
Apr 26, 2010, 6:25:24 PM4/26/10
to

I'm guessing that either (a) you don't permit a function to be
overloaded in two different translation units, or (b) functions
are not overloadable unless they're explicitly marked. Otherwise,
for any function you define, you'd have to allow for the possibility
that it might be overloaded later. (You might have explained this
before, but I don't remember the details.)

C++, as I recall, handles this by mangling all names, whether
they're overloaded or not.

If overloading were to be added to the C standard, there would be
some benefit in defining the mechanism to be as nearly compatible
with C++ as possible, so that, for example, you could easily call
a C++ overloaded function from C or vice versa. On the other
hand, there's also something to be said for avoiding some of the
complexities of C++ to minimize impact on C implementations.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Michal Nazarewicz

unread,
Apr 26, 2010, 6:40:28 PM4/26/10
to
Keith Thompson <ks...@mib.org> writes:
> If overloading were to be added to the C standard, there would be
> some benefit in defining the mechanism to be as nearly compatible
> with C++ as possible, so that, for example, you could easily call
> a C++ overloaded function from C or vice versa.

Yes, that was my intend when I was forming my though in the original
post.

> On the other
> hand, there's also something to be said for avoiding some of the
> complexities of C++ to minimize impact on C implementations.

This is why I proposed the `extern "C++"` marker. Without it function
works like plain old C function.

A thing to consider is weather the following should be valid:

double mysin(double x); /* unmangled */
extern "C++" float mysin(float x); /* mangled */
extern "C++" long double mysin(long double x); /* mangled */

jacob navia

unread,
Apr 26, 2010, 7:21:47 PM4/26/10
to
Michal Nazarewicz a écrit :

> Keith Thompson <ks...@mib.org> writes:
>> If overloading were to be added to the C standard, there would be
>> some benefit in defining the mechanism to be as nearly compatible
>> with C++ as possible, so that, for example, you could easily call
>> a C++ overloaded function from C or vice versa.
>
> Yes, that was my intend when I was forming my though in the original
> post.
>
>> On the other
>> hand, there's also something to be said for avoiding some of the
>> complexities of C++ to minimize impact on C implementations.
>
> This is why I proposed the `extern "C++"` marker. Without it function
> works like plain old C function.
>
> A thing to consider is weather the following should be valid:
>
> double mysin(double x); /* unmangled */
> extern "C++" float mysin(float x); /* mangled */
> extern "C++" long double mysin(long double x); /* mangled */
>

lcc-win uses "overloaded" as marker. This is less ambiguous as
extern C++
since it is clear what you are doing: overloading a function.

Automatic overloading must be avoided at all costs. It is a C++ bug.

C is another language. Modifying C so that all names are mangled would
be destroying the simplicity of the language for no reason.

When you want to overloaded you write:
"overloaded" and everyone knows what is going on.

Less typing can lead to less understanding from thepart of the READER of
the code, and we are all readers of code some day.

David R Tribble

unread,
Apr 26, 2010, 10:56:06 PM4/26/10
to
David R Tribble writes:
>> Adding true function overloading to C involves more than syntactic
>> sugar; it requires a fundamental change to the C linkage model.
>> This fact alone is enough to kill such a proposal dead in its
>> tracks.
>

Michal Nazarewicz wrote:
> I'm aware it's not just a trivial syntactic sugar, but it's not such

> a big change to linker model either. [...]


> Again, linkage model won't be changed -- only names will get mangled by
> the compiler so no changes in linker are required.

No, that really *is* a change to the linkage model of C
(as you can see by some of the other posts in this thread).
And it would force a change to *existing* linkers.

That is (for the time being, at least) enough to kill the idea,
given the nature of the the ISO C commitee with regards to
the existing state of the art.

FWIW, I don't like the limitations of existing C linkers, either,
but I don't see vast quatities of existing working code being
changed any time soon.

My proposal, or something like it, would be acceptable within
the existing state of the art of C compilers/linkers.

However, it also bears mentioning that the ISO committee has
stated as a goal of C1X that no new (invented) features will be
added to C (regardless of how many deficiencies that they fix
in the existing language or library).

Thus the only realistic way for a new feature to get adopted into a
future version of ISO C is for many vendors to begin implementing
that feature, so that it becomes widespread enough to be
considered de facto "existing art" at some point, and can be
codified as such by ISO.

-drt

Michal Nazarewicz

unread,
Apr 27, 2010, 4:16:15 AM4/27/10
to
> Michal Nazarewicz a écrit :

>> This is why I proposed the `extern "C++"` marker. Without it function
>> works like plain old C function.
>>
>> A thing to consider is weather the following should be valid:
>>
>> double mysin(double x); /* unmangled */
>> extern "C++" float mysin(float x); /* mangled */
>> extern "C++" long double mysin(long double x); /* mangled */

jacob navia <ja...@spamsink.net> writes:
> lcc-win uses "overloaded" as marker. This is less ambiguous as
> extern C++
> since it is clear what you are doing: overloading a function.

This however, introduces a "magic keyword" -- an identifier which is
treated as keyword depending on context. I think, if it is possible to
use an existing keyword it is better to do so.

Also, the `extern "C++"` mimics the `extern "C"` in C++ so it should be
familiar to many programmers and it allows for consistency with C++ (as
I mentioned earlier, it would be best if C also recognised `extern "C"`
as a no-op and C++ recognised `extern "C++"` as a no-op) whereas
"overloaded" introduces a completely new syntax.

jacob navia

unread,
Apr 27, 2010, 4:59:10 AM4/27/10
to
Michal Nazarewicz a écrit :

>> Michal Nazarewicz a écrit :
>>> This is why I proposed the `extern "C++"` marker. Without it function
>>> works like plain old C function.
>>>
>>> A thing to consider is weather the following should be valid:
>>>
>>> double mysin(double x); /* unmangled */
>>> extern "C++" float mysin(float x); /* mangled */
>>> extern "C++" long double mysin(long double x); /* mangled */
>
> jacob navia <ja...@spamsink.net> writes:
>> lcc-win uses "overloaded" as marker. This is less ambiguous as
>> extern C++
>> since it is clear what you are doing: overloading a function.
>
> This however, introduces a "magic keyword" -- an identifier which is
> treated as keyword depending on context. I think, if it is possible to
> use an existing keyword it is better to do so.
>

That is C++ solution, and it means that the poort "static" keyword is
misused for too mny different meanings.

Magic keywords (as you name them) has the advantage of being clear, and not
polluting the user name space.

The problem with extern C++ is that is completely different to C++
"extern C" keywords, even if they look deceptively similar.

It means ONLY that functions are overloaded. It is difficult to
unerstand the meaning of the code and can be misunderstood by many as
telling the compiler to use the whole C++ language within that declaration.

> Also, the `extern "C++"` mimics the `extern "C"` in C++ so it should be
> familiar to many programmers and it allows for consistency with C++ (as
> I mentioned earlier, it would be best if C also recognised `extern "C"`
> as a no-op and C++ recognised `extern "C++"` as a no-op) whereas
> "overloaded" introduces a completely new syntax.
>

Yes, because the IMPLICIT overloading of C++ is a problem for C. C and
C++ can't be compatible in this context and that is why I used a
completely new syntax.

You have never answered to the semantics here.

If we do NOT do automatic overloading we keep the C semantics:

(1) A normal function can't be overloaded implicitely later. It must
have an "overloaded" prototype, like all other C functions.
(2) Inconsistencies are caught by the compiler, not by the linker. In
C++ the automatic overloading leads to link errors if you overload by
mistake.

Please tell us what is your position here. As I showed you in another
message, C++ semantics CAN'T be used in C.

jacob

Michal Nazarewicz

unread,
Apr 27, 2010, 5:32:25 AM4/27/10
to
jacob navia <ja...@spamsink.net> writes:
> The problem with extern C++ is that is completely different to C++
> "extern C" keywords, even if they look deceptively similar.

My understanding of `extern "C"` is "use C mangling scheme which is no
mangling at all". In this context, `extern "C++"` would mean "use C++
mangling scheme".

> It means ONLY that functions are overloaded. It is difficult to
> unerstand the meaning of the code and can be misunderstood by many as
> telling the compiler to use the whole C++ language within that
> declaration.

I find that unlikely. The only C++ thing that could be used in function
declarations are templates and clearly declaring templates in C would
make little sense since you'd have no way of calling them anyway.

> Michal Nazarewicz a écrit :


>> Also, the `extern "C++"` mimics the `extern "C"` in C++ so it should be
>> familiar to many programmers and it allows for consistency with C++ (as
>> I mentioned earlier, it would be best if C also recognised `extern "C"`
>> as a no-op and C++ recognised `extern "C++"` as a no-op) whereas
>> "overloaded" introduces a completely new syntax.

> Yes, because the IMPLICIT overloading of C++ is a problem for C. C and
> C++ can't be compatible in this context and that is why I used
> a completely new syntax.

I don't see why they can't be compatible. I don't see your point.
If what I described was implemented the following would be perfectly
legal C and C++ code and it could be used in both C and C++ programs:

#v+


extern "C++" float mysin(float x);

extern "C++" long double mysing(long double x);
extern "C" int foo(void);
#v-

> You have never answered to the semantics here.

I thought I had...

> If we do NOT do automatic overloading we keep the C semantics:
>
> (1) A normal function can't be overloaded implicitely later. It must
> have an "overloaded" prototype, like all other C functions.

Yes, I stated this many times, to be able to overload function one has
to use the marker which I call `extern "C++"` and you call `overloaded`.

> (2) Inconsistencies are caught by the compiler, not by the linker. In
> C++ the automatic overloading leads to link errors if you overload
> by mistake.

I don't understand what you mean. What do you mean by overloading by
mistake? And how is it that C++ compiler cannot detect inconsistencies?

> Please tell us what is your position here. As I showed you in another
> message, C++ semantics CAN'T be used in C.

Obviously. Automatic overloading would break old code (meaning that new
code could not be linked with old object files), we all know and agree
on that.

Ian Collins

unread,
Apr 27, 2010, 6:31:57 AM4/27/10
to
On 04/27/10 09:32 PM, Michal Nazarewicz wrote:
> jacob navia<ja...@spamsink.net> writes:
>> The problem with extern C++ is that is completely different to C++
>> "extern C" keywords, even if they look deceptively similar.
>
> My understanding of `extern "C"` is "use C mangling scheme which is no
> mangling at all". In this context, `extern "C++"` would mean "use C++
> mangling scheme".

It means the function has C linkage. Name mangling is only part of the
picture. For example, it's unlikely but possible for a C++ compiler to
use different parameter ordering or register use for "normal" C++ functions.

The other problem is there isn't a standardised C++ mangling scheme!

>> It means ONLY that functions are overloaded. It is difficult to
>> unerstand the meaning of the code and can be misunderstood by many as
>> telling the compiler to use the whole C++ language within that
>> declaration.
>
> I find that unlikely. The only C++ thing that could be used in function
> declarations are templates and clearly declaring templates in C would
> make little sense since you'd have no way of calling them anyway.

Another would be reference parameters.

--
Ian Collins

Michal Nazarewicz

unread,
Apr 27, 2010, 7:14:35 AM4/27/10
to
> On 04/27/10 09:32 PM, Michal Nazarewicz wrote:
>> My understanding of `extern "C"` is "use C mangling scheme which is no
>> mangling at all". In this context, `extern "C++"` would mean "use C++
>> mangling scheme".

Ian Collins <ian-...@hotmail.com> writes:
> It means the function has C linkage. Name mangling is only part of
> the picture. For example, it's unlikely but possible for a C++
> compiler to use different parameter ordering or register use for
> "normal" C++ functions.

Granted. Overally it matches spirit of my wording.

> The other problem is there isn't a standardised C++ mangling scheme!

I don't see this as a problem. Or at least not a problem of C or C++
standard and not a reason why not allow function overloading. Note that
those standards do not standardise calling convention, type sizes, etc.

Lack of standard for name mangling is a nuisance but people learned to
live with it. I agree that it is a pain to declare C wrappers for C++
functions and method calls but all in all mangling is beneficial.

Explicit function overloading is value added. You don't have to use it
if you don't want to. This is a big difference from C++.

Adding support for name mangling does not break existing code. It also
does not force you to do anything. You would be able to still develop
library like you do now and everyone would be happy. At the same time
those who'd like to benefit from function overloading would be able to
do that. My proposal proposes *freedom* and I don't see why
standardised C++ name mangling would be crucial in any way.

>>> It means ONLY that functions are overloaded. It is difficult to
>>> unerstand the meaning of the code and can be misunderstood by many as
>>> telling the compiler to use the whole C++ language within that
>>> declaration.

>> I find that unlikely. The only C++ thing that could be used in function
>> declarations are templates and clearly declaring templates in C would
>> make little sense since you'd have no way of calling them anyway.

> Another would be reference parameters.

Yes, that too.

Personally, I'd love to see references in C.

James Kuyper

unread,
Apr 27, 2010, 8:18:51 AM4/27/10
to
Ian Collins wrote:
> On 04/27/10 09:32 PM, Michal Nazarewicz wrote:
>> jacob navia<ja...@spamsink.net> writes:
>>> The problem with extern C++ is that is completely different to C++
>>> "extern C" keywords, even if they look deceptively similar.
>>
>> My understanding of `extern "C"` is "use C mangling scheme which is no
>> mangling at all". In this context, `extern "C++"` would mean "use C++
>> mangling scheme".
>
> It means the function has C linkage. Name mangling is only part of the
> picture. For example, it's unlikely but possible for a C++ compiler to
> use different parameter ordering or register use for "normal" C++
> functions.

Just to expand on that brief comment: there's two very different things
that C++ language linkage can refer to:

Identifiers with external linkage, whether objects or functions, can
have language linkage, which means that their names are handled in a
manner appropriate for linkage with code written in the specified
language. For "C++" language linkage, this basically means name
mangling. For other languages, it can mean other things - for instance,
I've found that, in order to for a C function to be compatible with
Fortran, the C version of the function's name often has to differ from
the Fortran version, by the addition of an underscore at the beginning,
or at the end, or at both, depending upon the platform and the Fortran
compiler. This is something that would be covered, in C++, by using
'extern "Fortran"' on the identifier.

Function types can also have language linkage, which means that the
interface is handled in a manner appropriate for linkage with code
compiled using the specified language.

Using a language linkage specification directly on a function's
declaration causes both kinds of language linkage to occur, but it is
possible to separate the two kinds of linkage. A function typedef
declared with one language linkage could be used in the declaration of a
function that explicitly has a different language linkage. The resulting
function's type would have the first language linkage, but it's name
would have the second one.

This could be used, for instance, to create a function whose name has
C++ language linkage, and could therefore only be referred in unmangled
form by C++ code, but with a type that has C language linkage, which
would allow a pointer to that function to be passed to C code, where it
could be dereferenced.

Keith Thompson

unread,
Apr 27, 2010, 12:52:44 PM4/27/10
to
Michal Nazarewicz <min...@tlen.pl> writes:
> jacob navia <ja...@spamsink.net> writes:
[...]

>> (1) A normal function can't be overloaded implicitely later. It must
>> have an "overloaded" prototype, like all other C functions.
>
> Yes, I stated this many times, to be able to overload function one has
> to use the marker which I call `extern "C++"` and you call `overloaded`.

I'm very uncomfortable with the idea that, to enable a feature that
could be used in pure C code, you have to refer to C++.

I'm also a bit uncomfortable with the idea of a non-reserved keyword.
It's probably workable, and it probably wouldn't cause any real
confusion in practice unless you're writing deliberately writing
obfuscated code, but it still makes me nervous. It introduces a
completely new kind of lexical element, one that's not used anywhere
else in the language.

A couple of admittedly ugly alternatives:
extern "overloaded"
_Overloaded

The point is that if we're going to introduce a new feature, I'd ideally
like to define the syntax the way it would have been defined if it had
been in the language from the beginning. Of course this isn't always
possible, but I think it's worth some effort to try to get close to that
ideal.

(Not that the committee is likely to accept the idea.)

[...]

Michal Nazarewicz

unread,
Apr 27, 2010, 3:03:43 PM4/27/10
to
Keith Thompson <ks...@mib.org> writes:

> Michal Nazarewicz <min...@tlen.pl> writes:
>> jacob navia <ja...@spamsink.net> writes:
> [...]
>>> (1) A normal function can't be overloaded implicitely later. It must
>>> have an "overloaded" prototype, like all other C functions.
>>
>> Yes, I stated this many times, to be able to overload function one has
>> to use the marker which I call `extern "C++"` and you call `overloaded`.
>
> I'm very uncomfortable with the idea that, to enable a feature that
> could be used in pure C code, you have to refer to C++.

No matter, the functionality would have to be implemented the same way
as in C++, so why not say: "Hey, compiler, if you are also capable of
compiling C++, use the same call method and mangling you use for C++".

> The point is that if we're going to introduce a new feature, I'd ideally
> like to define the syntax the way it would have been defined if it had
> been in the language from the beginning. Of course this isn't always
> possible, but I think it's worth some effort to try to get close to that
> ideal.

I agree but in this situation I believe `extern "C++"` is the best from
all proposed syntaxes so far.

> (Not that the committee is likely to accept the idea.)

Which is, in my opinion, a pity...

Keith Thompson

unread,
Apr 27, 2010, 3:32:40 PM4/27/10
to
Michal Nazarewicz <min...@tlen.pl> writes:
> Keith Thompson <ks...@mib.org> writes:
>
>> Michal Nazarewicz <min...@tlen.pl> writes:
>>> jacob navia <ja...@spamsink.net> writes:
>> [...]
>>>> (1) A normal function can't be overloaded implicitely later. It must
>>>> have an "overloaded" prototype, like all other C functions.
>>>
>>> Yes, I stated this many times, to be able to overload function one has
>>> to use the marker which I call `extern "C++"` and you call `overloaded`.
>>
>> I'm very uncomfortable with the idea that, to enable a feature that
>> could be used in pure C code, you have to refer to C++.
>
> No matter, the functionality would have to be implemented the same way
> as in C++, so why not say: "Hey, compiler, if you are also capable of
> compiling C++, use the same call method and mangling you use for C++".

extern "C++" would have to, among other things, specify the
name-mangling scheme used by some specific C++ implementation.
Why should that be relevant to a pure C program? For that matter,
what if a given platform has a C implementation but no C++
implementation? Surely function overloading in pure C would be
just as useful on such a system as anywhere else.

ANSI C borrowed the idea of function prototypes from C++. Would it
have been reasonable for the syntax to refer to "C++"?

Though I have some qualms about jacob's proposed non-reserved keyword
"overload", I must say I like it a lot better than extern "C++".
(Nothing personal.)

Michal Nazarewicz

unread,
Apr 27, 2010, 4:39:49 PM4/27/10
to
>> Keith Thompson <ks...@mib.org> writes:
>>> I'm very uncomfortable with the idea that, to enable a feature that
>>> could be used in pure C code, you have to refer to C++.

> Michal Nazarewicz <min...@tlen.pl> writes:
>> No matter, the functionality would have to be implemented the same way
>> as in C++, so why not say: "Hey, compiler, if you are also capable of
>> compiling C++, use the same call method and mangling you use for C++".

Keith Thompson <ks...@mib.org> writes:
> extern "C++" would have to, among other things, specify the
> name-mangling scheme used by some specific C++ implementation.

No. It's not C standard's concern the same as standard does not specify
the exact specifics of types, etc.

> Why should that be relevant to a pure C program? For that matter,
> what if a given platform has a C implementation but no C++
> implementation? Surely function overloading in pure C would be
> just as useful on such a system as anywhere else.

Exactly the same can be said about a theoretical pure C++ implementation
and `extern "C"`. I think you are insisting on creating a problem where
there is none.

> ANSI C borrowed the idea of function prototypes from C++. Would it


> have been reasonable for the syntax to refer to "C++"?

Not necessarily, because the prototypes do not impose changed call
method and it was possible to add function prototypes in a backward
compatible way.

> Though I have some qualms about jacob's proposed non-reserved keyword
> "overload", I must say I like it a lot better than extern "C++".
> (Nothing personal.)
>
> [...]

--

Keith Thompson

unread,
Apr 27, 2010, 5:17:19 PM4/27/10
to
Michal Nazarewicz <min...@tlen.pl> writes:
>>> Keith Thompson <ks...@mib.org> writes:
>>>> I'm very uncomfortable with the idea that, to enable a feature that
>>>> could be used in pure C code, you have to refer to C++.
>
>> Michal Nazarewicz <min...@tlen.pl> writes:
>>> No matter, the functionality would have to be implemented the same way
>>> as in C++, so why not say: "Hey, compiler, if you are also capable of
>>> compiling C++, use the same call method and mangling you use for C++".
>
> Keith Thompson <ks...@mib.org> writes:
>> extern "C++" would have to, among other things, specify the
>> name-mangling scheme used by some specific C++ implementation.
>
> No. It's not C standard's concern the same as standard does not specify
> the exact specifics of types, etc.

It's not the standard's concern, but the implementation certainly has to
be aware of it.

But there's no good reason to require such awareness for a feature to be
used in pure C programs.

Function overloading, if it's to be added to the language, should be a
pure C feature, at least potentially.

Ada has overloaded functions too; why not use extern "Ada"? Or extern
"Objective-C"?

>> Why should that be relevant to a pure C program? For that matter,
>> what if a given platform has a C implementation but no C++
>> implementation? Surely function overloading in pure C would be
>> just as useful on such a system as anywhere else.
>
> Exactly the same can be said about a theoretical pure C++ implementation
> and `extern "C"`. I think you are insisting on creating a problem where
> there is none.

The problem is largely esthetic. If you want C to define a mechanism
for interfacing with C++, that's fine, and extern "C++" is a perfectly
sensible syntax for it. If you want C to define function overloading,
that's fine too. I object to tying those two features together.

>> ANSI C borrowed the idea of function prototypes from C++. Would it
>> have been reasonable for the syntax to refer to "C++"?
>
> Not necessarily, because the prototypes do not impose changed call
> method and it was possible to add function prototypes in a backward
> compatible way.

So add overloading in a backward compatible way as well.

Francis Glassborow

unread,
Apr 27, 2010, 6:01:47 PM4/27/10
to
Keith Thompson wrote:
> Michal Nazarewicz <min...@tlen.pl> writes:
>>>> Keith Thompson <ks...@mib.org> writes:
>>>>> I'm very uncomfortable with the idea that, to enable a feature that
>>>>> could be used in pure C code, you have to refer to C++.
>>> Michal Nazarewicz <min...@tlen.pl> writes:
>>>> No matter, the functionality would have to be implemented the same way
>>>> as in C++, so why not say: "Hey, compiler, if you are also capable of
>>>> compiling C++, use the same call method and mangling you use for C++".
>> Keith Thompson <ks...@mib.org> writes:
>>> extern "C++" would have to, among other things, specify the
>>> name-mangling scheme used by some specific C++ implementation.
>> No. It's not C standard's concern the same as standard does not specify
>> the exact specifics of types, etc.
>
> It's not the standard's concern, but the implementation certainly has to
> be aware of it.
>
> But there's no good reason to require such awareness for a feature to be
> used in pure C programs.
>
> Function overloading, if it's to be added to the language, should be a
> pure C feature, at least potentially.
>
> Ada has overloaded functions too; why not use extern "Ada"? Or extern
> "Objective-C"?
>

Or why not:

extern "Overloaded"

Once you recycle extern in the form

extern string literal function declaration

you can choose any suitably descriptive string literal.

jacob navia

unread,
Apr 27, 2010, 6:11:51 PM4/27/10
to
Francis Glassborow a écrit :

> Or why not:
>
> extern "Overloaded"
>
> Once you recycle extern in the form
>
> extern string literal function declaration
>
> you can choose any suitably descriptive string literal.

What happens if you want to declare an overloaded function static?

You would have monstruosities like:

extern static int "Overloaded" foo(void);

The problem with "recycling" extern with an overloaded meaning (pun
intended) is that it leads to conflicts with other keywords like static.

Besides, it is

extern static int "Overloaded" fn(void);

accepted?

It should be if we follow the "in any order" rule.

I have yet to see a serious contender for my implementation:

static int overloaded fn(void);
overloaded must be immediately before fn.

static double overloaded = 45.234;

is accepted.

Keith Thompson

unread,
Apr 27, 2010, 7:33:08 PM4/27/10
to
jacob navia <ja...@spamsink.net> writes:
> Francis Glassborow a écrit :
>> Or why not:
>> extern "Overloaded"

I'd prefer "overloaded", but ...

>> Once you recycle extern in the form
>>
>> extern string literal function declaration
>>
>> you can choose any suitably descriptive string literal.
>
> What happens if you want to declare an overloaded function static?
>
> You would have monstruosities like:
>
> extern static int "Overloaded" foo(void);
>
> The problem with "recycling" extern with an overloaded meaning (pun
> intended) is that it leads to conflicts with other keywords like
> static.
>
> Besides, it is
>
> extern static int "Overloaded" fn(void);
>
> accepted?
>
> It should be if we follow the "in any order" rule.

The biggest problem with Francis's suggestion, IMHO, is that it
conflates overloading with external linkage. There's no reason
not to support overloaded functions with internal linkage. jacob,
I think that's more or less the point you're making.

> I have yet to see a serious contender for my implementation:
>
> static int overloaded fn(void);
> overloaded must be immediately before fn.
>
> static double overloaded = 45.234;
>
> is accepted.

My only problem with that (other than the question of whether the
feature of overloading should be added to the language at all)
is that it introduces the new concept of a non-reserved keyword.
That's certainly not a fatal flaw, but I'd like to see a syntax
that fits in more cleanly with the existing language (I mean that
in a deeper sense than not breaking existing code). Which is why
I suggested a new _Overloaded reserved keyword, probably treated
as a function-specifier so it fits into the syntax the same way
"inline" does.

What would you think of this?

void "overloaded" func(int);
void "overloaded" func(double);

Would permitting "overloaded" (or "overload") to appear as the first
token of the declaration cause parsing problems?

Or:

#pragma STDC OVERLOAD func
void func(int);
void func(double);

I'm not pleased with that either; #pragma just seems like the wrong
mechanism for this.

0 new messages