This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: type based aliasing again


> >This statement implies that the code, as written, has *always*
> >been incorrect.
> 
> Exactly.
> 
> >I believe this is a false premise.  Standards change.
> 
> Not in this respect, apparently.

As I understand it, we are talking about a change that moves a construct
from "undefined" to "incorrect".

IOW, before this kind of optimization was attempted, such code may
not have been legal, but it wasn't illegal, either. . . it was
undefined, right?

If you are saying that such code has always been *defined* as
illegal, then I guess I am really confused . . . as I started
programming back when C was what K&R said it was, and I don't
remember this as being defined as illegal back then.

> Nobody has, to my knowledge, proposed
> that -traditional imply -fno-alias-analysis, which suggests K&R I
> indeed, as has been reported, left this behavior undefined.

Perhaps nobody has proposed that explicitly, and perhaps that is
because people want a compromise: *intelligent* alias analysis
that allows for old code to continue to work, but in some cases,
the optimization can and will occur.

Or, maybe not.

Maybe it's just me! ;->

> The resulting statement is not equivalent to the other quote
> you made up.

I am not making up quotes.  I never claimed to be quoting, I was
paraphrasing.

> But the bug is in the user code being compiled, not in GCC.  Period.
> There's *no* credible disagreement on that.

Excuse, but the point I'm making is: there isn't necesarily a bug
in *either* of them.  It doesn't have to be a yes/no, black/white,
binary kind of thing.

It isn't a mistake to use philips head screws.  It isn't a mistake to
buy a flat head screw driver.  It *is* a mistake to use a flat head
screw driver on a philips head screw.

Of course, I may be misunderstanding the issue, here, as well.

> >With the caveat (of course) that behaviour should not change so long
> >as the code conforms to the standard that the compiler purportedly
> >conforms to, right?
> 
> Incorrect.  See "implementation-defined".  When you change implementations,
> which can include switching to a new version, you can change behaviors.

And, I think, that is where this discussion starts to unravel.  The
weight various groups give to avoiding such changes varies from zero
to very large.

My impression is that your "avoiding implementation dependent change"
priority is near zero, and that in general, you are arguing for this
to be the default GCC philosophy.

Correct me (as I'm sure you will) if my understanding is in error. :-)

> But it's *my* responsibility as a vendor of a free-software tool
> to make it work for any conforming C compiler support GNU CC extensions
> that compiles my code without error.  The aliasing bugs in the code
> are *my* bugs, not examples of GCC compiling it erroneously.

And where we differ is in your use of the term: "bug".  I wouldn't consider
either GCC, or your program, to be buggy.  The act of mixing
incompatible pieces is probably a mistake, though.

> It is not in any way the responsibility of the GCC development team
> to make sure I don't have to actively maintain *my* software just
> so users will magically get the right overall behavior.

And I don't believe that anybody is actually advocating this.

I do see people saying that, in effect, that some kind of compromise
is the best solution when *all* factors are considered.

> >Heck, they shouldn't be allowed anywhere near powered machinery
> >of any sort what so ever.
> 
> One could at least argue they shouldn't be programming (for others
> anyway) at all, but I used to say stuff like that, and, looking back,
> I realize that...well, come to think of it, I shouldn't have been
> programming for other people at all!  But how else to learn?  ;-)

Personally, I don't believe in the "throw them in, let them sink or
swim" approach to learning.

People that *have* to have this environment to learn should not,
at the very least, be allowed to play with anything that might
injure or kill others (learning not to point a loaded gun at
somebody should not be something you learn by trial and error).

> >C requires a huge amount of discipline to use correctly, and well.
> 
> Perhaps.  Anyone who agrees with that should pause and consider
> this: C++ is to C what the space shuttle is to a paper airplane.
> (Okay, I'm exaggerating...a *bit*.  ;-)

Well . . . my personal opinion re: C++ falls into the category:
inflamatory language, which is something I urge you to avoid.

> >Ditto.  As far as I can remember, the aliasing rules are *NEW*, so
> 
> No, they just weren't so widely exploited by compilers.

Which begs the question: did K&R define this behavior as
"buggy"/illegal?  I don't remember ever seeing this as being
defined, explicitly, as illegal.

If so, then you are correct.  If not, I must politely differ with
you.

And yes, there are still very large bodies of code that are,
in general, K&R C and no "higher".

> No, I was specifying something decidedly, if only "just barely",
> different: that a programmer maintaining code with this alias
> bug is *the* one responsible for either *fixing* the code,

I don't disagree that the programmer who is maintaining the code
is responsible, I am simply saying that in some cases, there may
not *be* anybody currently maintaining that code.

IMO, documentation that says, "use this switch", and some reasonable
attempt on the part of the GCC maintainers to make sure that when
that switch (plus whatever other switches are required) is used,
that the compiler generates code that is as close as possible to
that generated by earlier versions, is sufficient.

I am aware of the difficulty involved.  What isn't clear, is just
where to draw the line.

> *or*
> taking responsibility for specifying exactly what compiler(s)
> users should use that he believes do *not* happen to expose the
> bugs in his code.

And here we get back to this concept of: "bug".  Digging out my old
K&R book, and taking a long look, I don't see anything that would
indicate that this kind of code is, in fact, a *BUG*.  Dangerous,
undefined, etc.  But not a bug.

So a good faith effort to conform to earlier definitions of what
the "C" language was, and what a particular construct should do
should not be labeled a "bug", just because the language definition
has changed.

> (I don't know offhand, and so don't want to discuss, whether these
> were bugs that were easy to avoid by reading the docs, 'cause I
> think they weren't...though I think they were easy to avoid by writing
> to the ISO C, or an earlier, standard, i.e. I think the bug had
> to do with relying on *very*-GCC-specific extensions.)

The bugs (as is almost always the case), fell into all four
categories:

1) GCC bugs.
2) Linux source code bugs.
3) Miscommunication bugs.
4) Interface change bugs.

> I've been thinking today about how this is really a black-box vs.
> white-box problem, in the context of the larger issue of engineering.

[Some stuff re: complexity deleted.  Please refer to the original email
 for details.]

> (In this
> case, the complexity of GCC far exceeds that of ISO C itself,
> from the point of view of a programmer writing ISO C code.  So
> as soon as that programmer strays outside ISO C into GCC-specific
> behavior, the complexity of the task he's undertaking goes *way*
> up, even if he sees a modest reduction in the complexity of the
> *code* he writes.)

Not necesarily.  Consider the task of writing an OS kernel that is
supposed to be portable across multiple architechtures.

Adding a few extensions to GCC actually makes the system *less*
complex, because it localizes and minimizes the changes necesary.

In short, the responsibility is semi-atomic, and a good design would
assign this responsibility to GCC.

> [Snippage re: opaque vs. transparent objects.]

Agreed.  But GCC extensions do not make the GCC transparent.  They
simply add interface.

>   -  Minimize the number of components.

Disagree.  It isn't number that counts, it's number of *different*
*types* (classes) of components that count, in combination with
a number of other factors, including object transparency, use
or lack thereof of polymorphism, number of interconnections
(appropriate use of such design patterns as Facade, for example).

And more.

>   -  Rely as much as possible on only the published, black-box behavior
>      of components.

Agreed.  But GCC extensions are, indeed, published black-box behavioral
descriptions.

> To the extent this is well-done, the project can tolerate replacement
> and upgrade of components, as well as debugging of problems, since
> there's more of an opportunity to find a smoking gun in terms of
> which component (or connecting tissue, itself a component) is failing.

This is the basic, underlying assumption in object oriented maintenance.

> If I allow bugs in my code on the grounds that I can make GCC "cope"
> using an option, then I increase the "whiteness", or translucency,
> of the GNU C compiler component.

Disagree.  Instantiation with parameters does not increase the
transparency of the instantiated object.

It does increase the complexity of the interface somewhat, but this
can be controlled by making absolutely sure of your design . . .
IOW, instantiation parameters should be restricted to control
parameters only (IOW, "configuration").

> Right there, that increases complexity.
> So, replacing GCC with a much earlier, or much later, version
> can break things, if that version doesn't support that option.

This breakage should be one way.  Once introduced, a switch
should not be removed.  It may end up doing nothing much later
on (and indeed, there are already examples of this in other
GNU programs/projects/tools/systems).  But a switch (a
"control" parameter) should never be removed.

> But, moreso, leaving my code in a buggy state increases *its*
> complexity as well, since that code is not ISO C, which means
> anyone working on it besides me (in the sense that I, too,
> am a "component" of the system and thus might be replaced or
> upgraded ;-) has *more* complexity to deal with, because just
> knowing ISO C, an off-the-shelf component, is not enough to
> understand the code.

Correct.  This is an inescapable result of growth . . . as things
grow, they grow more complex.

Arguing against adding *unnecesary* complexity is entirely reasonable
and correct.  The question at hand is: is the addition of the
complexity currently under discussion worth it (eg, reasonable)?

> Now, if that explains my overall thinking clearly enough, perhaps
> you can see why I positively *discourage*, and don't mind GCC
> *itself* discouraging, programmers viewing GCC as a white box
> rather than a black box.

And so far, nothing I've seen in this discussion actually
translates into making GCC a white-box object.

Add interface, yes.  But nobody has suggested that you: "open up the
workings of GCC and make it part of the program being compiled".

> So, when I hear people say "GCC should default to -fno-alias-analysis",
> I *basically* hear them as if they're complaining about code that
> either isn't important enough to have been engineered in the first
> place,

This is an unfair and inaccurate characterization.

> In both cases, I tend to think "why should we increase GCC's complexity
> to address cases that either don't matter

This is your opinion.  You are free to state it.  The GCC user (as by
now is abundantly clear) does not share your opinion on what "matters".

A compromise is in order.  A good engineer cares about what his
customers/users care about.

> or are time-bombs waiting
> to explode anyway?"

One could characterize any-and-every software system in existence as
a "time-bomb waiting to explode".

I don't necesarily see that as being productive, though.

> it's obviously vastly harder here in GCC-land, so it's not unreasonable
> to declare that these issues will no longer be discussed, and that
> GCC is no longer to be assumed a warning generator, since that'd
> be a simplifying assumption consistent with the core engineering
> function of GCC.)

This assumption makes GCC a smaller, less complex component . . . at
the cost of making the *whole* system *MUCH* more complex.

Trading a small complexity reduction in one component of a system
for a *large* increase in the complexity of the system as a whole
is not a good engineering decision.

> Because remember: when you ask for a black-box product to adopt
> behaviors that are white-box-like

This statement seems to be based on the false premise that adding
interface, makes an object more transparent (it does not).

> (which includes many compiler
> warnings, especially these),

Compiler warnings are interface (think: return codes if that makes
it any easier).  They may add to the complexity of
the object (the object in question being the GNU C compiler)
but they do not make the object transparent.

> you ask for an *increase* in the
> complexity visible to end users,

No.  I ask for a *decrease* in ambiguity, and an *increase* in the
specificity and the total amount of "dialog".

The success of the GUI simply proves what has been known for a
very long time: dialog is better than monologue, and monologue
is better than no communications what-so-ever.

> Now, to people who say "forget all the engineering BS, I just
> want to get real work done", I say, fine, you don't want to
> do engineering?  Then be happy with the fact that some version
> of GCC happened to compile your code so it worked at a given
> moment.

That last is a basic truth . . . because no matter how hard you
try, no compiler will ever be 100% ISO C compliant except by 
the most improbable and unlikely intervention of pure luck.

> The central hypocrisy of much of this thread (*not* jstevens here,
> I must stress!) is that some people want to insist that GCC behave
> *as if* it is perfectly engineered -- works the same way all
> the time in any project in which its used, despite being upgraded,
> enhanced, and fixed -- but *refuse* to acknowledge, or recognize,
> the responsibility *we*, as GCC *developers*, have to exercise
> some engineering methodologies to make GCC actually *work*.

Obviously GCC must change.  And these changes should, when consistent
with the goals of the GNU project, be compliant with existing standards.

Just as obviously, some changes will break old code.  Perfect backwards
compatibility is impossible when change is also occurring.

The issue at hand isn't black and white, though.  The issue is: how
to reduce the total complexity of the system.  And this system is
more than just GCC.

It is (the following list is no where near complete): GCC, GCC users,
GCC maintainers, the body of existing code out there that might/must
be compiled with GCC.

As time goes by, and the very oldest code slowly "fades away", some
of the old support structures can be removed.

> In short: if you care about engineering, you don't mindlessly complain
> about GCC not issuing warnings

And, as stated above, I disagree with your assessment re: warnings
and complexity.

If, to understand a warning, you have to "pop the hood" and dig into
GCC source code, then I would agree with you.  But a simple warning,
issued by the compiler in situations that indicate a program may
possibly be non-conformant, actually *decreases* the complexity of
the system as a whole.

The above statement is dependent on where you draw the boundaries of
"the system", of course.

> If you *don't* care about engineering, then you have no business
> complaining that GCC should accommodate broken code either, since
> that code is either *hacked* (and thus will always need fixing as
> components change around it) or *engineered* (in which case it *must*
> be fixed).

And here in lies the very core of this disagreement: you seem to miss
other, valid interpretations, such as:

The code *WAS* engineered, but either the language definition, or
the compiler, changed *AND* it is far to expensive to change all of the
code to match the new definition or compiler at this time, *BUT*
the new compiler *MUST* be used.

Obviously, some of the people who are complaining,
could simply continue to use the old compiler . . . and probably
should.

Others should simply set the proper switches.

And yet others should do as you recommend: change their code.

> When people treat GCC not issuing the exact same warnings given
> the exact same code from one version to next as yet another case
> of GCC "breaking" their code

This, I would agree, is unreasonable, and fits within the range
of "implementation defined behaviors" that a user must expect to
change . . . with the caveat that there should be a good reason
for the change, and that reason should be communicated to the user.

> Simply put: give 'em an inch, and they'll take a mile.

A trifle hostile, that.  And not generally applicable, either.

Bringing us back to: inflamatory language. ;->

> Does anyone really think users *then* will accept the resulting
> lack of warnings about bugs in their code any more than they'll
> accept the present situation?

Probably not.  And rightfully so, especially if no warning of
any kind was given about this change.  Unavoidable change is
unavoidable change.  But not taking *any* care re: avoiding
unnecesary-and-avoidable-interface-changes is *VERY* poor
engineering.

> (Maybe *the* kindest is to shoot the horse -- i.e. remove any and
> all support for -fno-alias-analysis in GCC 3, 2.96, or even 2.95.2.

Which begs the question: just how interested are the GCC maintainers
in whether or not they have any users?  In how satisfied their users
are in the product?  In how the product is viewed by potential users?

> >As for avoiding the issue by adding warnings: I agree.  You will not
> >avoid this issue by adding warnings.  But you can, I trust, see
> >how the warnings are necesary?
> 
> No, warnings are never necessary for a compiler to emit,

Wrong.  Warnings are absolutely required under the principle of
"communicate".

The most basic, most important facet of human factors engineering
is: talk to the user.  The second is: avoid surprise.

This (talk!) is in fact the root of the success of the GUI: the GUI
is a system that implements a (mostly) static dialog . . .
which is immensely better than no communication at all, when
dealing with human beings.

> GCC emitting warnings is a quality-of-implementation issue,

No, it's a human factors issue (which may be included under
quality-of-implementation [QOI], depending on how you define QOI).

> and
> thus should *only* be done when the advantages of issuing the
> warnings *greatly* overwhelms the disadvantages of added complexity
> to GCC to support the warnings.

Warnings should be issued *even* *if* adding them increases internal
complexity of the object.

The least complex object is that which has no interface at all, but
that object is hardly useful, now is it?

> The throw-everything-into-a-single-program mentality

Warnings do not fall into that category.  Warnings are analogous
to return codes from functions that do input parameter checking.

> I.e. what you, as a programmer, should be using to find bugs
> in your code are programs that have the *sole* purposes of
> finding static, and dynamic, bugs, respectively.

Wrong.  Since it is the responsibility of the compiler to define
proper-and-appropriate (since the standard allows for: implementation
defined, as well as undefined), therefore it is the responsibility
of that object (the compiler), to communicate this knowledge to
the user.

Now, the current "compiler" is already an aggregate, and if you
are suggesting that different objects have different responsibilities,
and therefore are responsible for generating different classes of
warnings, then I suspect everybody would agree with you.

If you are suggesting that GCC should not produce diagnostics
at all, I suspect that very few people would agree with you.

The reasonable course lies somewhere in the middle.

John S.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]