This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Anonymous Namespaces
- From: Chris Lattner <sabre at nondot dot org>
- To: Gabriel Dos Reis <gdr at integrable-solutions dot net>
- Cc: gcc at gcc dot gnu dot org, Kevin Atkinson <kevina at gnu dot org>,Andrew Pinski <pinskia at physics dot uc dot edu>
- Date: Sat, 31 Jan 2004 16:49:54 -0600 (CST)
- Subject: Re: Anonymous Namespaces
On 31 Jan 2004, Gabriel Dos Reis wrote:
> Chris Lattner <sabre@nondot.org> writes:
> | Ok, that makes sense. When export is an issue, this can certainly be
> | corrected. Link time is "soon enough" for LLVM's purposes anyway.
>
> In fact, even without export implementation the issue is still there,
> right now! The following example is for the inclusion model (the one
> g++ currently implements).
<snip>
> During the instantiation of n::func(T, U) with T = my::fu, U = my::mu,
> argument-dependent name lookup will find gunc() in the unnamed namespace
> in my:: because it has external linkage. However, if you change gunc()
> to a static function, then name look up will not succeed. You'll be
> incorrectly rejecting a well-formed program. So, no "export" needed to
> illustrate the problem. You can start reverting your transmutation :-/
Listen to be _very_ carefully. The parser is completely unmodified in the
LLVM transformation: the change occurs in _expand_, so it only effects the
generated LLVM code. You can verify this with the LLVM demo page, which
correctly compiles and optimizes your program, in this case, down to the
equivalent of 'int main() {}'. When does native GCC 3.4 produce? GCC 3.3
with -O3 produces a .s file with 54 lines of X86 code.
> Now, with export, the issue is more involved because the defintion of
> n::func() could be exported, i.e. defined in a separate translation
> unit. But then in the translation unit that contains the invokation
> to n::func(), there is evidence that my::gunc() is used. Only the
> instantiation unit will tell you. So, in translation-unit-at-time
> mode, in general, you don't have enough information to decide. You
> need to go to the instantiation unit.
Fine, again, _when_ this is an issue, it can be dealt with.
> | That is exactly what I'm talking about. I'm very confused here. In LLVM,
> | the source-level notion of internal linkage is very different from the
> | LLVM notion of internal linkage.
>
> But then use a difference terminology if you don't want to confuse
> yourself (or a C++ programmer talking with you). A C++ programmer knows
> what "static" and "internal linkage" means in C++. If you change
> those phrases to mean something different from what they do in a C++
> programme source, you better accurately state their meanings. Using a
> different word is far better.
I'm sorry, but I'm not confused. The LLVM notion of internal linkage is
the standard one, and corresponds exactly to what the 'static' keyword
does at global scope. Unnamed namespaces are NOT the same as internal
linkage, but can be transformed to be implemented in terms of it in this
case.
> | I haven't change the C++ front-end at
> | all in this respect, just the LLVM code that gets generated. As such,
> | there is no way that name lookup could be effected.
>
> It depends on what form of inputs you generate your code from.
Please provide more details.
> | > I strongly advise against a naive approach to this issue, that would
> | > not have an understanding of unnamed namespace semantics, C++ name |
> > lookup rules and exported templates. | | Again, I emphasize that the
> LLVM treatment of this results in | _dramatically_ better code, and has
> zero semantic implications since | 'export' has not been implemented
> yet.
>
> As I just showed, "export" is not needed to illustrate the fundamental
> semantic problem. I understand you rank speed over correctness, but we
> cannot afford transmuting people's programs in a way that changes their
> meanings.
That is incorrect.
> | > | Also, you can't mark a class 'static' (making the member
> | > | functions, vtables, rtti info, etc all internal).
> | >
> | > So what? What you want is not "static" but a way to say "this thing
> | > is used only in this translation unit".
> |
> | _exactly_, which is something that you cannot do without unnamed
> | namespaces!
>
> Again, as I said earlier and illustrated above, functions declared
> in an unnamed namespace can "escape", so an unnamed namespace does not
> do what you think it does.
Not without export!
> | For example, if a (nonvirtual) method is only called from one
> | call site, and its class is in an anonymous namespace, it _should be
> | inlined_ into that call site, (almost) regardless of how big it is.
> | There are many other examples of this kind of thing. How do you achieve
> | this without anonymous namespaces behaving sanely?
>
> But an unnamed namespace does not guarantee that an entity defined in it
> does not escape! See the example above.
Again, you are confusing notions in the C++ front-end with notions in the
optimizer/code generator.
> | Transforming objects in unnamed namespaces to use LLVM internal linkage
> | cannot cause any regressions from an unmodified G++ front-end. In the
> | future, the addition of export may not make this true, but if so, it can
> | be dealt with then. Also, it does not appear to me that export will be
> | added to g++ anytime in the near future. I find it ridiculous that you
> | advocate non-LLVM G++ to generate pessimal code in the meantime.
>
> What is ridiculous is you not understanding how unnamed namespace and
> C++ name lookup rules work and saying I'm ridiculous when I'm telling
> you that your statement does not match C++ rules -- not mentioning your
> use of "static" and "internal linkage" in totally different and
> undefined way.
When you made this statement, you were confused. If you still are,
please reask, and I will respond.
> You're free to implement whatever you like in your research compiler.
*sigh*, LLVM's goals are for it to be as stable and reliable as a
commercial grade compiler, not for it to be "research quality". Please do
not sling insults unless you've _actually tried it out_. Thanks. In
fact, I think if you did, you would find it optimizes C++ programs
_substantially_ better than GCC does, and takes less time to do so. Your
example is just one case, there are many others.
> What, however, is not correct is your using "static" and "internal
> linkage" in very sneaky ways to mean totally different things in a
> discussion where people are already confused about the semantics of
> unnamed namespaces and static.
Uh, okay... I did not realize I was being sneaky!
> And, I'm not advocating people generate pessimal code. I'm telling
> people that they should teach the inliner about unnamed namespaces
> instead of transmuting meanings of well-defined codes.
Again, as I said before, the inliner is not the only thing that cares,
please read the examples I gave in my previous email.
> But of course, if the only thing you measure is speed and you rank it
> over correctness, you may not understand what I'm saying.
As with any compiler vendor, in LLVM, we consider correctness the #1
concern, after that we want excellent performance from the generated code
and efficient compile times.
-Chris
--
http://llvm.cs.uiuc.edu/
http://www.nondot.org/~sabre/Projects/