GCC is re-implementing in C++ and C discarded

L

lovecreatesbeauty

What? No, N1570 never mentions `int main(){}`. It presents two

Hi Keith,

Maybe that's print error then, i guess.

n1570, sec 6.5.3.4 p8 / page 91. similar code repeated on other pages in this doc.

n1256 has this too.

--vvvv--

N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x

size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}

int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}

Forward references: common definitions <stddef.h> (7.19), declarations (6.7),
structure and union specifiers (6.7.2.1), type names (6.7.7), array declarators (6.7.6.2).

6.5.4 Cast operators

--^^^^--
 
J

Jens Gustedt

Am 28.08.2012 01:43, schrieb Keith Thompson:
And if `void foo() { }` does provide a prototype, then *that*
needs to be made clearer; there are a lot of compilers that fail
to warn about calls like `foo(42)`.

Please re-read what I have stated in my previous post. The definition
of the term function prototype is not given syntactically but
semantically: a declaration of a function that declares the types of
its parameters, that's it.

void foo() { }

perfectly fits this definition, so this declaration includes a
prototype.

The only nitpick that you could find here is the use of "specifies"
versus "declares", so one could want to do a corrigendum

6.7.6.3p14: "An empty list in a function declarator that is part of a
definition of that function *declares* that the function has no
parameters."

But you'd have to do a lot of hairsplitting to actually see the
difference between a "declaration that specifies something" and a
"declaration that declares something".

Jens
 
J

Jens Gustedt

Am 28.08.2012 03:16, schrieb Vincenzo Mercuri:
Il 28/08/2012 02:34, Keith Thompson ha scritto:
[..]
Removing `main` from the debate for a moment, clearly the following
function definition is valid:

void foo() { }

But does this function definition:

void foo() {
if (0) foo(42);
}

require a diagnostic?

I agree with what you said. I believe that there is no way to answer to
this question, unless the Standard explicitly says that, in such cases,
"void foo() { }" also provides a prototype for `foo()'.

But it says so implicitly. Prototypes are defined semantically
(6.2.1p2), not through syntax: a declaration of a function that
declares the types of its parameters. "void foo() { }" perfectly fits
in here, it is a definition and it specifies the number and type of
its parameters, namely none.

Jens
 
K

Keith Thompson

lovecreatesbeauty said:
Maybe that's print error then, i guess.

n1570, sec 6.5.3.4 p8 / page 91. similar code repeated on other pages
in this doc.

Right, it occurs exactly twice, in *non-normative* examples. I hadn't
been aware of that. See my recent followup in this thread to "eq mail".

My argument about what the normative text of the standard implies still
stands (I think); it is at least unclear.

[...]
 
V

Vincenzo Mercuri

Il 28/08/2012 09:07, Jens Gustedt ha scritto:
Am 28.08.2012 03:16, schrieb Vincenzo Mercuri:
Il 28/08/2012 02:34, Keith Thompson ha scritto:
[..]
Removing `main` from the debate for a moment, clearly the following
function definition is valid:

void foo() { }

But does this function definition:

void foo() {
if (0) foo(42);
}

require a diagnostic?

I agree with what you said. I believe that there is no way to answer to
this question, unless the Standard explicitly says that, in such cases,
"void foo() { }" also provides a prototype for `foo()'.

But it says so implicitly. Prototypes are defined semantically
(6.2.1p2), not through syntax: a declaration of a function that
declares the types of its parameters. "void foo() { }" perfectly fits
in here, it is a definition and it specifies the number and type of
its parameters, namely none.

I'd have preferred the Standard to be more clear about that.
My "beloved clang" warns about "no previous prototype" even if such a
function is correctly defined before its call. If a definition with empty
parentheses provides a "degenerate case of prototype" should at least
be stated once and for all (even if I'd say that it would be a step
backward for the Standard: definitions/declarations with empty parentheses
have been "marked" as obsolescent since ANSI C). We also should correct
ourselves for the many times we have said that a prototype is a kind of
declaration but not all the function declarations are prototypes: now
we have to say that this is true for declarations themselves and false
for declarations provided by definitions? This would be much more
confusing.
I think the goal of a Standard should be to make things clearer, then
I'd expect the Standard to remove what it called "obsolescent" for more
than two decades :)
 
M

Malcolm McLean

בת×ריך ×™×•× ×©× ×™,27 ב×וגוסט 2012 16:48:29 UTC+1, מ×ת Vincenzo Mercuri:
Then you should program in C++. If you need those extra features in the
C language you need C++. Demanding the Standard to make such a huge
change to the language is just nonsensical (to me).
Declaring a library to be standard isn't really a huge change to the language.

If you added syntactical support for linked lists, queues, and so on that
would be a change. But there's no real need to do that.
 
J

Jens Gustedt

Am 28.08.2012 13:47, schrieb Vincenzo Mercuri:
(even if I'd say that it would be a step
backward for the Standard: definitions/declarations with empty parentheses
have been "marked" as obsolescent since ANSI C).

I only find the following:

6.11.6 Function declarators

The use of function declarators with empty parentheses (not
prototype-format parameter type declarators) is an obsolescent
feature.

6.11.7 Function definitions

The use of function definitions with separate parameter identifier
and declaration lists (not prototype-format parameter type and
identifier declarators) is an obsolescent feature.

with what I said early this only makes declarations with empty list
that are not definitions an obsolescent feature. And as we see from
the start of the discussions, these should really be kept, for the
sake of compatibility with C++.

But I agree that all of this could be stated more directly :)

Jens
 
R

Rui Maciel

Vincenzo said:
I think it is implementation-defined whether it is supported or not,
even though almost all the implementations do support it. But I'd say
that it is not the "most portable" way to define main.

Maybe you are thinking about C++ programs written for a freestanding
environment. Anyhow, if you need to define main(), you either define it as
int main() or int main(int argc, char *argv[]).


Rui Maciel
 
V

Vincenzo Mercuri

Il 28/08/2012 22:11, Rui Maciel ha scritto:
Vincenzo said:
I think it is implementation-defined whether it is supported or not,
even though almost all the implementations do support it. But I'd say
that it is not the "most portable" way to define main.

Maybe you are thinking about C++ programs written for a freestanding
environment. Anyhow, if you need to define main(), you either define it as
int main() or int main(int argc, char *argv[]).

I was only referring to the C language there. Thanks however for
your explanation :)
 
K

Keith Thompson

Rui Maciel said:
Vincenzo said:
I think it is implementation-defined whether it is supported or not,
even though almost all the implementations do support it. But I'd say
that it is not the "most portable" way to define main.

Maybe you are thinking about C++ programs written for a freestanding
environment. Anyhow, if you need to define main(), you either define it as
int main() or int main(int argc, char *argv[]).

For C++:

It shall have a return type of type int, but otherwise its type is
implementation-defined. All implementations shall allow both of the
following definitions of main:
int main() { /* ... */ }
and
int main(int argc, char* argv[]) { /* ... */ }

So those are the only two *portable* forms, but others are permitted
if the implementation supports them. There's even a note: "It
is recommended that any further (optional) parameters be added
after argv."

And of course C has the "or in some other implementation-defined
manner" clause.
 
R

Rui Maciel

Kenny said:
Q: What exactly do we mean when we say that language A is more "popular"
than language B?

I'm not in the position to state what you believe, but I can speak for
myself and provide a definition for "popular" in this context which I
believe is appropriate.

As the word "popular" refers to something that is regarded with favour or
approval by people in general, then, as a programming language is supposed
to be a tool used by programmers to actually write software, a good
yardstick for the popularity of a programming language is how widespread is
its use to actually develop programs. A couple of ways which adequately
evaluate this are:
a) the number of programs which are developed, completely or in part, with
it
b) the demand for programmers who are skilled in it

A quick search in monster.com for ads listing Objective-C as a required
skill returns 417 results.[1] Meanwhile, there are 1000 ads looking for
C++[2] or C[3] programmers, and I suspect that the site caps search results
at 1000 hits. To me, this information is more meaningful than the number of
times a certain string is found in a random blog.


Rui Maciel

[1] http://jobsearch.monster.com/search/?q=Objective__2DC-Programming-
Language
[2] http://jobsearch.monster.com/search/?q=C__2B__2B-Programming-Language
[3] http://jobsearch.monster.com/search/?q=C-Programming-Language
 
F

Fritz Wuehler

Steven G. Kargl said:
Steven G. Kargl said:
On Fri, 24 Aug 2012 13:58:46 -0400, Kenneth Brody wrote:

On 8/24/2012 5:15 AM, Nick Keighley wrote:
[...]
this whole conversation strikes me as bizzare. A kind of level
confusion. It reminds of one of my collegues who came out with "C++ is
upwards compatible with C because it is implemented in C" and couldn't
see what was wrong with that statement.

"Assembler must be upwards compatible with C, because 'as' is written in C."

"FORTRAN must be upwards compatible with C, because gnu FORTRAN is written
in C." (I think.)

The name of the language is "Fortran". It's been Fortran since
the Fortran 1990 standard.

So what? FORTRAN is no less FORTRAN now then it was then. Perhaps he was
talking about gnu's shitty F77 compiler.

Except even your spelling in all caps is incorrect. If you take that time
to look at the Fortran standards, you find that the 'ORTRAN' is written in
a small cap font. After 25 years, is it asking to much to spell the
name of the language correctly?

Many people have no respect for tradition and they seem to think everything
was created after they were born. In reality, FORTRAN was designed and
produced by IBM and came to the rest of the world around 1957. That language
and those implementations are still in regular use. The fact a new language
called Fortran that is a superset of FORTRAN was standardized does not
change the fact FORTRAN was and still is FORTRAN.

Consider a few references:

"The Origins of FORTRAN" presentation by Peter Crouch.
"American National Standard FORTRAN" USAS X3.9-1966
"American National Standard Programming Language FORTRAN" X3.9-1978

It's funny how you think 25 years is such a long time since FORTRAN has been
around for almost 56 years.
GNU GCC does not have a shitty F77 compiler. g77 was deprecated years
ago.

Ok, but doesn't gfortran support F77 and isn't F77 FORTRAN? I mean, even you
capitalized the name ;-)
Since April 20, 2005, the Fortran compiler in GCC is gfortran, and for the
last few years gfortran has been competitive with all commercial available
Fortran compilers.

On what basis do you claim gfortran is competitive? I'm not saying it isn't
(I certainly doubt that it is but I didn't say that until you said it
is). gcc gives very poor diagnostics and the code generation on platforms
other than Intel is known to be subpar. I'm sure Solaris Studio spanks
gfortran badly on SPARC but thankfully I haven't had to test it.
Yes, I did. But, you failed to read the next sentence. When you build
GCC with gfortran support, the m4 files are processed to generated some
Fortran code for the runtime library. That Fortran code is then compiled
by the just built Fortran compiler.

I understood you the first time. I object to the complexity of using an
arcane scripting language in a compilation system and to gcc's general
approach of expediency uberalles instead of discipline. Total ad-hoc
"design" and complete absence of engineering, that's gcc.
Your response is a classic example of someone who does not understand
the principle of using the right tool to get a job done.

I don't agree, but I do say yours is a classic example of having no discipline
in design or coding. Anything goes, right buddy?
Have you tried compiling any Fortran code with LLVM? LLVM does not have
its own Fortran compiler. It actually uses gfortran.

Well no, I haven't. I use IBM FORTRAN IV and occasionally their VS FORTRAN,
and Solaris Studio. Thankfully I only hear about gcc from my disadvantaged
friends.
http://llvm.org/Features.html

"Front-ends for C, C++, Objective-C, Fortran, etc based on the GCC 4.2 parsers."

I can assure you that GCC 4.2.x's Fortran parser is fairly bad compared to
any of the newer versions.

I don't dispute that. I'm just happy llvm will be an alternative for people
currently forced to use the shitty gnu tools. Eventually I suspect gcc will
only exist on Linux since the FSF serfs want to eliminate the LGPL on the
runtime. Free, open source software (BSD or MIT licensed) will probably move
to clang/llvm. FreeBSD moving away from gcc to clang is a great milestone in
free software history and against the tyranny of the FSF and its lemmings.
 
E

eq mail

Am 25.08.2012 21:23, schrieb James Kuyper:
???
The claim was that use of C was a necessity, not just a convenience. C
doesn't have constructors, and designated initializers are only a
convenience feature that don't do anything that can't already be done
using ordinary initializers - they just make it more convenient.

How would you do

unsigned char errVector[] = { [EINVAL] = true, [ERANGE] = true, };
enum { maxNeeded = sizeof(errVector), };

in C++ ?

(I apologize for this bunch of C++ in a technically unrelated group,
for those offended.)

This question caught my attention: can this be done? This certainly
falls into the "there's many a way to do this" basket in C++, and
perhaps (like mostly anything) with enough Boost magic and repetitive
overloads, it has always been possible; however, I sought for a
(relatively) expressive solution using the relatively powerful
variadic templates, and came up with this. (Someone better than me
might come up with something cleaner, as most would agree that this
*is* rather wieldy.)

#include <array>
#include <cstddef>
#include <type_traits>

template<std::size_t i, std::size_t... Rest>
struct indices {
typedef typename std::enable_if<sizeof...(Rest) != 0,
indices<Rest...>>::type next;
static constexpr std::size_t value = i,
max = (value + 1 > next::max)
? value + 1
: next::max;
};
template<std::size_t i>
struct indices<i> {
typedef void next;
static constexpr std::size_t value = i,
max = value + 1;
};

template<class U, std::size_t N, class T>
constexpr typename std::enable_if<std::is_void<T>::value, U>::type
get()
{
return U();
}
template<class U, std::size_t N, class T, class V, class... Rest>
constexpr typename std::enable_if<!std::is_void<T>::value, U>::type
get(V&& v, Rest&&... rest)
{
return (T::value == N)
? std::forward<V>(v)
: get<U, N, typename T::next>(std::forward<Rest>(rest)...);
}

template<class U, class Indices, std::size_t... Gen, class... Rest>
constexpr typename std::enable_if<sizeof...(Gen) == Indices::max,
std::array<U, Indices::max>>::type
make_(Rest&&... rest)
{
return {{get<U, Gen, Indices>(std::forward<Rest>(rest)...)...}};
}
template<class U, class Indices, std::size_t... Gen, class... Rest>
constexpr typename std::enable_if<sizeof...(Gen) != Indices::max,
std::array<U, Indices::max>>::type
make_(Rest&&... rest)
{
return make_<U, Indices, Gen..., sizeof...(Gen)>(
std::forward<Rest>(rest)...);
}
template<class U, std::size_t... Indices, class... Rest>
constexpr std::array<U, indices<Indices...>::max> make(Rest&&... rest)
{
return make_<U, indices<Indices...>>(std::forward<Rest>(rest)...);
}

.... and what does all of this accomplish? Not a whole lot; at least
not without something similar to the code below (this is a scenario
from a later reply, because the one above seemed too simplistic.)

auto errVector = make<const char*, EBADF, 0, ERANGE>(
"EBADF", "(success)", "ERANGE");
enum { maxNeeded = sizeof(errVector) };

'errVector' above is actually not an array, but rather a std::array
object. It's unavoidable, but luckily std::array is just a very simple
wrapper of one.

One could perhaps achieve something to this end with structs, too,
although the syntax might be relatively even more awkward. (It's
certain that the members would have to be "listed" in some way as
there's no other way to get to know of them.) I'm not 100% certain
about this being doable, however.

....

Now that we've come this far, intuition begs the question: do the C++
folk actually believe they've got the superior tools when they refuse
to incorporate designated initializers into the language, when it's
obvious to anyone that they don't (have them).

I don't think the situation is that simple.

The way I see it, the co-operation of the committees will mostly
revolve around and result in not introducing subtle incompabilities
(the ones that won't show up when compiling) into the languages; and
not in extending the usable common subset of them. Static
initialization, I think, is often simply seen as less important within
C++ circles, because with complex objects you have lots to do at
runtime anyway.

By the way, with only a few values far between, one might want to use
an associative container instead of a mostly-wasted array. C++ has
relatively expressive syntax for those (shown below), but I don't
think C is getting anything similar anytime soon, tricks or not.

std::unordered_map<int, const char*> errMap = { { ERANGE, "ERANGE" },
{ 0, "(success)" }
/* ... */
};
 
L

lawrence.jones

Jens Gustedt said:
But it says so implicitly. Prototypes are defined semantically
(6.2.1p2), not through syntax: a declaration of a function that
declares the types of its parameters. "void foo() { }" perfectly fits
in here, it is a definition and it specifies the number and type of
its parameters, namely none.

It's always been understood that a declaration of a function has to use
a parameter-type-list to declare the types of its parameters; being part
of an old-style definition that uses an (optional) identifier-list is
not sufficient, even though the definition does go on to declare them.
There are lots of tidbits scattered through the rest of the standard
that make it obvious that that was the committee's intent, but it could
have been stated more explicitly.
 
J

Jens Gustedt

Am 31.08.2012 23:40, schrieb (e-mail address removed):
It's always been understood that a declaration of a function has to use
a parameter-type-list to declare the types of its parameters;

Out of curiosity, why did the term prototype then never make it to a
syntactical definition? Do you agree with me that if we stick together
the current text as it stands we have that

- "void foo() { }" is a defintion of "foo"
- it is also a declaration
- it declares that "foo" has no parameters
- so it also declares the types of these parameters (namely none)
- so it is a declaration of "foo" that declares the type of its parameters
- according to 6.2.1p2 it is a prototype
being part of an old-style definition that uses an (optional)
identifier-list is not sufficient, even though the definition does
go on to declare them. There are lots of tidbits scattered through
the rest of the standard that make it obvious that that was the
committee's intent, but it could have been stated more explicitly.

Honestly I didn't find much information that would really suggest
that. If I haves seen correctly, there are two examples in the
standard of "int main() { ... }". Doesn't suggest much that the
committee really wants everybody to move to the "int main(void) { ... }"
form.

I don't even think that is very productive to stick to that idea. Old
style function declarations with empty list that are not prototypes
should have disappeared since long. What is left is just a gratuitous
discrepancy to C++.

In any case, this deserves a DR and a clarification.

Jens
 
S

Szabolcs Nagy

Jens Gustedt said:
Out of curiosity, why did the term prototype then never make it to a
syntactical definition? Do you agree with me that if we stick together
the current text as it stands we have that

- "void foo() { }" is a defintion of "foo"
- it is also a declaration
- it declares that "foo" has no parameters
- so it also declares the types of these parameters (namely none)
- so it is a declaration of "foo" that declares the type of its parameters
- according to 6.2.1p2 it is a prototype

the type is not declared
In any case, this deserves a DR and a clarification.

what about

http://www.open-std.org/JTC1/SC22/wg14/www/docs/dr_317.htm

so foo has no prototype, but i don't think this
contradicts the statement that

void foo() {}

and

void foo(void) {}

are equivalent function definitions
 
J

Jens Gustedt

Am 03.09.2012 02:31, schrieb Szabolcs Nagy:
the type is not declared

I think that it is not easily apparent how an empty list could declare
the type of parameters that don't exist.

That is not what I meant by clarification. Do we want to have a state
where the standard can only be understood if you know about a body of
"judgements" by the committee that makes this or that interpretation
valid or not?

What I mean with clarification is to add something to the standard
that makes this situation clearer, the same way as it had been done
for the type-punning via unions, e.g.

What I even would prefer is to abandon all non-prototype declarations
and definitions. They have been declared obsolete since long. A first
step could be to exactly allow for the empty-list definition to be a
prototype. This would put C in accordance with C++ on that point, with
not much cost.

Jens
 
J

Jens Gustedt

Am 03.09.2012 08:31, schrieb Jens Gustedt:
Am 03.09.2012 02:31, schrieb Szabolcs Nagy:

I think that it is not easily apparent how an empty list could declare
the type of parameters that don't exist.

And syntactically the only way to parse the parameter list of "void
foo(void);" according to the BNF of the standard is "D(
identifier-listopt )", too. So saying that the syntax distinguishes
the forms of specifying an empty list, is simply not true.

Jens
 
I

Ike Naar

And syntactically the only way to parse the parameter list of "void
foo(void);" according to the BNF of the standard is "D(
identifier-listopt )", too. So saying that the syntax distinguishes
the forms of specifying an empty list, is simply not true.

(identifier-listopt) cannot expand to (void)
because void is not an identifier (it's a keyword).
 
C

Chicken McNuggets

In the case of Objective-C, approximately everyone and their idiot
brother is developing iOS apps. So there's lots of talk about the
relatively new platform. By contrast, C (and C++) is much better
understood, and I'd guess that the relative amount of chatter is lower
compared to the amount of actual work being done.

This argument would make sense if C was lower on the Tiobe index than
Objective-C but it is not. So the metrics that the Tiobe index uses show
that C is still widely discussed (and by extension) widely used.

In fact as the link I posted above shows C is the most discussed
language on the web, ahead of Java, Objective-C and C++ (and everything
else besides).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,077
Messages
2,570,569
Members
47,206
Latest member
MalorieSte

Latest Threads

Top