Author Topic: GCC attributes  (Read 27598 times)

Offline Der Meister

  • Regular
  • ***
  • Posts: 307
GCC attributes
« on: December 16, 2005, 09:31:01 pm »
From revision 1502 on a file named 'src/sdk/gcc-attribs.h' entered the project. At first this seems to be no problem but in revision 1507 there were massive changes to this file. One of the changes was adding the makro __const__. This breaks (at least vor me) the codestats plugin (and possible more - it could even break the whole project. Seems as this didn't happen yet, I fear it could do it when nobody would expect it.). The problem is: The file '/usr/include/bits/mathcalls.h' contains lines like the following:
Code
__MATHCALLX (ceil,, (_Mdouble_ __x), (__const__));
Now guess what happens  :?
GCC throws lots of weired error messages. Error messages that seem to have no sense at all.
That is the best example why praeprocessor macros are evil. It took me two hours to find the reason for that problem.

Anyway, why is Code::Blocks even using gcc extensions? Using compiler specific things (especially compiler specific extensions) is a very bad practice (at least in my opinion). Is there any reason why Code::Blocks now uses them? It should be a very very good one - or I'll be rather disappointed.  8)
Real Programmers don't comment their code. If it was hard to write, it should be hard to understand.
Real Programmers don't write in BASIC. Actually, no programmers write in BASIC, after the age of 12.

Offline rickg22

  • Lives here!
  • ****
  • Posts: 2283
Re: GCC attributes
« Reply #1 on: December 16, 2005, 10:38:52 pm »
Let's see what WebSVN says...
Quote
Rev: 1507
Path: /trunk/src/sdk/gcc-attribs.h
Author: thomasdenk
Age: 2 days
Log message:
Changed gcc attribute macros to lowercase for better readability.
Changed likely() and unlikely() so they work with arbitrary values.
Added some more attribute macros.
Added attributes to the block allocator and to code completion.
Marked Manager::isappShutingDown() as deprecated.

Edit: I mailed him, I'm sure it'll be fixed in the next revision.
« Last Edit: December 16, 2005, 10:53:09 pm by rickg22 »

takeshimiya

  • Guest
Re: GCC attributes
« Reply #2 on: December 16, 2005, 10:47:23 pm »
Don't we love SVN?  :)
Yes.
And TortoiseSVN have a function just for this.

Just go to /src/sdk, and right-click on gcc-attribs.h ->TortoiseSVN->Blame.
And then, it will tell you the person to blame. :D

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: GCC attributes
« Reply #3 on: December 17, 2005, 12:39:38 am »
Well, apologies for your inconvenience. What can I say... the macro redefines a keyword, which is of course illegal (but which normally works nevertheless). I'll change the macros so they use single underscores instead of double underscores, this should fix your problem.
And yes, you are right, this is a good example why macros are evil.

Anyway, why is Code::Blocks even using gcc extensions? Using compiler specific things (especially compiler specific extensions) is a very bad practice (at least in my opinion). Is there any reason why Code::Blocks now uses them? It should be a very very good one - or I'll be rather disappointed.  8)
This is easily explained. I introduced gcc extensions because they are there, and because you can use them. It is bad practice to use them if you do not take provisions that you can still use other compilers, but these were taken. The macros evaluate to a gcc attribute definition when compiled with gcc, and to an empty string in all other cases. I do not see that as bad practice, I see it as making use of features which are useful. For example, if(unlikely(ptr == 0)) gives valuable hints to the compiler - the branch for the null pointer is almost never taken, and gcc is able to optimize the code accordingly. On compilers other than gcc, unlikely(x) evaluates to (x), so you don't really give away anything.
Another good example is the function IsAppShutingDown. This function is misspelled, but for backwards compatibility, it is still in the API. Now, thanks to attributes, that function is marked with the deprecated attribute. Not only can you see it in the header, but if you actually use that function, gcc will tell you that it is deprecated and you should not be using it. I see that as an improvement.

The problem you encountered is not due to using attributes, but because I chose a bad macro name. Prior to 1507, the macros were in capitals, but PURE and DEPRECATED are so darn ugly, hence I changed them. __const__ and __inline__ were indeed bad choices, granted.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline Urxae

  • Regular
  • ***
  • Posts: 376
Re: GCC attributes
« Reply #4 on: December 17, 2005, 01:06:07 am »
[The risk of taking a long time to post: you get beaten to it :?]

From revision 1502 on a file named 'src/sdk/gcc-attribs.h' entered the project. At first this seems to be no problem but in revision 1507 there were massive changes to this file. One of the changes was adding the makro __const__. This breaks (at least vor me) the codestats plugin (and possible more - it could even break the whole project. Seems as this didn't happen yet, I fear it could do it when nobody would expect it.). The problem is: The file '/usr/include/bits/mathcalls.h' contains lines like the following:
Code
__MATHCALLX (ceil,, (_Mdouble_ __x), (__const__));
Now guess what happens  :?
GCC throws lots of weired error messages. Error messages that seem to have no sense at all.
That is the best example why praeprocessor macros are evil. It took me two hours to find the reason for that problem.

Well kids, remember this: don't use names that are reserved for the (C++) implementation, such as those containing a double-underscore, except as defined in the documentation of that same implementation :P.

Quote
Anyway, why is Code::Blocks even using gcc extensions? Using compiler specific things (especially compiler specific extensions) is a very bad practice (at least in my opinion). Is there any reason why Code::Blocks now uses them? It should be a very very good one - or I'll be rather disappointed.  8)

First thing, notice that the entire contents of the file (except include guards) are contained in an #if __GNUC__ >= 3 / #else / #end block, so the use of the macros defined in it shouldn't cause any problems on compilers other than gcc. (at least not on ones that don't define __GNUC__, which would be rather improper to do if you're not 100% source-compatible with gcc)

The reason to use such attributes is generally that they provide the compiler with extra information about your program that it can use to optimize it better. Since they are compiler specific extensions however, syntax and availability differs between compilers and thus packaging such attributes in macros is the usual solution. MSVC has extensions for at least some of those used in the file using the __declspec syntax, for example.
The reason to expand to nothing if not compiled on gcc instead of using those attributes is likely that C::B currently (AFAIK) doesn't compile on any other compilers anyway. If it did, they could be defined to something else in an #elif clause for other compilers.

Offline rickg22

  • Lives here!
  • ****
  • Posts: 2283
Re: GCC attributes
« Reply #5 on: December 17, 2005, 01:12:57 am »
It's interesting to see how different people think differently (doh). Thomas has an obsession with optimizing the implementations (i.e. blockallocator), while i have an obsession with optimizing the algorithms. I think we make a good combination :)

takeshimiya

  • Guest
Re: GCC attributes
« Reply #6 on: December 17, 2005, 01:22:29 am »
Urxae is right, never define something starting with an _ (underscore) or __ (double underscore), because those are reserved for usage by the implemetator of the standard library, so it's probable to have name clashes.

As Stroustrup says also, having macros in UPPERCASE helps. Appart, as they are a little more hard to read, you try to not use them whenever possible.

Also, wxWidgets have interesting macros in defs.h, and IMHO you should use them whenever possible (don't reinvent the well :)) like:

/*  Macro to issue warning when using deprecated functions with gcc3 or MSVC7: */
#if wxCHECK_GCC_VERSION(3, 1)
    #define wxDEPRECATED(x) x __attribute__ ((deprecated))
#elif defined(__VISUALC__) && (__VISUALC__ >= 1300)
    #define wxDEPRECATED(x) __declspec(deprecated) x
#else
    #define wxDEPRECATED(x) x
#endif


So, if you are about to introduce a new macro that it's not defined in wxWidgets, a good name would be something as cbUNLIKELY.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: GCC attributes
« Reply #7 on: December 17, 2005, 01:48:19 am »
Thanks, I knew about these, but I don't like their syntax (putting everything into a macro argument), and they only define a few attributes. For example, you cannot write int someFunction() wxDEPRECATED; which is a lot better to read.

Also, wxWidgets is notorious about defining really sick macros (#define new) and using attributes incorrectly. Have you ever wondered why wxWidgets produces about 100.000 warnings during a normal compile? Most of them are related to incorrectly used attributes.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

takeshimiya

  • Guest
Re: GCC attributes
« Reply #8 on: December 17, 2005, 03:59:22 am »
Also, wxWidgets is notorious about defining really sick macros (#define new) and using attributes incorrectly.
First, it can be disabled with wxUSE_GLOBAL_MEMORY_OPERATORS.
Second, they must have a reason for doing that.
Third, if you are complaining about that, why don't send a feature request or patch?
Four, if you know things that you think are wrong in wxWidgets itself, and can do nothing about it, could you make a separate thread (or @WiKi) indicating things to "avoid" in wxWidgets, so other users can benefit from that.

Now back on topic:
Saying that wxDEPRECATED(x) is harder to read is an opinion. In my view, is better because: it's capitalized, and it notes that the entire macro is applied.
However all of thatisn't that important compared to this:

While your someFunction() cbDEPRECATED works on GCC, it doesn't work on Visual C, because the declaration is inverted cbDEPRECATED someFunction().

So, putting everything into a macro argument like wxDEPRECATED(x) is the only solution.
You said "I knew about these", but it seems you didn't read what the wx #define does and how it does.

I hope you'll understand.

Offline Urxae

  • Regular
  • ***
  • Posts: 376
Re: GCC attributes
« Reply #9 on: December 17, 2005, 06:25:34 am »
Urxae is right, never define something starting with an _ (underscore) or __ (double underscore), because those are reserved for usage by the implemetator of the standard library, so it's probable to have name clashes.

While true, the complete rules are a bit more complex:

In C, the implementation reserves
  • any global-scope name beginning with _
  • any name beginning with _ followed by an upper-case letter
  • any name beginning with __
C++ additionally reserves any name containing __ anywhere in it, not just at the beginning.

Also, "the implementation" covers both the standard library and the compiler itself.

Offline Urxae

  • Regular
  • ***
  • Posts: 376
Re: GCC attributes
« Reply #10 on: December 17, 2005, 06:46:50 am »
Now back on topic:
Saying that wxDEPRECATED(x) is harder to read is an opinion. In my view, is better because: it's capitalized, and it notes that the entire macro is applied.

It's an opinion I agree with though. Wrapping the entire declaration in a macro makes it harder to see what is being declared, or that it is in fact a declaration at all. Not to mention what happens when you want to apply multiple attributes...

Quote
However all of thatisn't that important compared to this:

While your someFunction() cbDEPRECATED works on GCC, it doesn't work on Visual C, because the declaration is inverted cbDEPRECATED someFunction().

So, putting everything into a macro argument like wxDEPRECATED(x) is the only solution.

It's not. At least not if MSVC and GCC are your targets, I don't know how other compilers handle attributes.
You forgot an option: just use cbDEPRECATED someFunction(). My g++ accepts attributes in that location:
Code
D:\Temp>cat test.cpp
void __attribute((deprecated)) f() {}

int main()
{
    f();
}

D:\Temp>g++ test.cpp
test.cpp: In function `int main()':
test.cpp:5: warning: `f' is deprecated (declared at test.cpp:1)
test.cpp:5: warning: `f' is deprecated (declared at test.cpp:1)

Anyone want to bet why this works, by the way?
My money is in order to support exactly this situation: using macros to apply attributes without having to wrap the entire declaration in them ;).

takeshimiya

  • Guest
Re: GCC attributes
« Reply #11 on: December 17, 2005, 07:43:16 am »
It's ok if GCC supports that then. But are you sure that works on any gcc version?

And you'll certainly will want to hope that no other compiler handles that in a different way.

With the other way however, you don't have to worry about future/other compilers.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: GCC attributes
« Reply #12 on: December 17, 2005, 01:15:53 pm »
It's ok if GCC supports that then. But are you sure that works on any gcc version?

And you'll certainly will want to hope that no other compiler handles that in a different way.

With the other way however, you don't have to worry about future/other compilers.
No, some of these attributes only work with gcc version >= 3.

You saw the #if, didn't you :)
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline Urxae

  • Regular
  • ***
  • Posts: 376
Re: GCC attributes
« Reply #13 on: December 17, 2005, 09:57:53 pm »
Quote from: Thomas (SVN rev. 1542 comment)
Replaced double-underscore macros with triple-underscore due to problems encountered with codestats plugin.

While this may solve the immediate problem, it doesn't fix the underlying cause. You're still using names that are reserved to the compiler and standard library. Please reread my post above:
In C, the implementation reserves
  • any global-scope name beginning with _
  • any name beginning with _ followed by an upper-case letter
  • any name beginning with __
C++ additionally reserves any name containing __ anywhere in it, not just at the beginning.

Triple underscores still contain double underscores, plus they begins with a double underscore, plus they're in the global scope (macros are in every scope :() so even that clause is violated here. In fact, the only clause this doesn't violate is the one about underscore-upper case letter, simply by virtue of not containing any uppercase letters.

How about something like cb_inline_/cb_inline? Or just going back to upper case: cb_INLINE_/cb_INLINE? They're macros, general convention is that they contain a lot of (if not only) uppercase symbols anyway...

Oh, and looking over that patch I noticed something else: The deprecated attribute on Manager::isappShutingDown() is at the end of the line. As mentioned in earlier posts it'll need to be more to the front for MSVC, and GCC accepts it there too. Might be a good idea to move it, though by the time MSVC is supported that method may have been removed completely already ;).

takeshimiya

  • Guest
Re: GCC attributes
« Reply #14 on: December 18, 2005, 01:46:27 am »
I vote for cbEVILMACRO convention.