Hacker News new | comments | show | ask | jobs | submit login
Compiler Warnings for Objective-C Developers (oleb.net)
58 points by Garthex 1606 days ago | hide | past | web | 28 comments | favorite

'Treat warnings as errors' is the greatest thing since shirt pockets. I've found that most warnings are really latent errors. I've been using this setting for as long as I've been compiling with GCC/LLVM, going back to gcc 2.x.

Whenever I take over a new project I immediately endeavor to fix all the warnings. The reason is simple: I've spent too much time chasing bugs that were directly related to a specific warning in a sea of them. Once you get a project warning-free it's quite easy to keep it that way.

Regarding the author's specific complaint--unused variables--I find that it's quite simple to comment out the declaration. There's no need to resort to pragmas in this instance.

Have you ever worked on a project that has to build on diverse systems that you may not control, like most open source projects?

Inflicting -Werror on yourself is fine, but inflicting it on others is onerous, because there's no way you can guarantee that your code produces no warnings on their compiler with their library and header versions.

>Inflicting -Werror on yourself is fine, but inflicting it on others is onerous, because there's no way you can guarantee that your code produces no warnings on their compiler with their library and header versions.

This is precisely the reason it is in fact necessary.

When writing code that is intended to be portable and is expected to generate reproducible floating-point calculations in numerically intensive calculations, warnings on different platforms and header versions is a godsend.

When I receive a bug report that says, "I am using operating system distribution X, version Y, with library version Z, and specific test W produces warnings when I type `make check`," it makes me happy.

Why not just use #error? Then the build will crap out in any event. I've found #error to work on a wider range of compilers anyway (I'm not sure #warning is standardized).

I think I would deal with this on a case-by-case basis. If the project was primarily for Objective-C/Apple I think I would use -Werror against the most recent set of tools. My experience writing software for the iOS platform indicates this wouldn't be an onerous initial constraint. And, there's nothing to stop others from changing the build settings.

I would absolutely relax the constraint if I was maintaining a large cross-platform OSS project. In that case, I think your criticism is on point. I hadn't considered this situation as I've not been the maintainer of such a system.

The build machine should treat warnings as errors but for local builds warnings are acceptable. You know they can't be checked in but they don't get in your way and slow you down while writing new code.

I never really understood this, what's stopping you from resolving those warnings even if they won't make the build fail? I mean, you still get a list of all the warnings and you can still have a zero-warnings rule (which is something you should really do)? This is, in my opinion, exactly as pointless as my wife setting her alarm clock seven minutes forward in order to stop herself from being late.

There are two scenarios. In one, you control the build process yourself, in which case nothing is physically stopping you. There is still value in doing it, because we are irrational creatures. We may be more likely to let a "warning" slide, rather than an "error," even though it is only classified as an error because we told it to do so. Being irrational creatures, we are loathe to go back on past decisions, and turning an "error" back into a "warning" requires action on our part that implies we were wrong before. We're more likely to just fix the "error."

The second situation is when you don't control the build process, in which case someone or someones are keeping you honest.

Have you ever tried to spot a warning in a large project with hundreds of files? It's nearly impossible as all those build commands fly by. Note that I'm speaking to a more traditional Unix Make environment. Therefore, it's easier to fail on that specific file than to let the build continue.

Certainly building with a tool like Xcode makes the warnings more conspicuous, and you can just choose to fix all warnings. I don't see anything wrong with that approach, but I still prefer to just treat the warnings as errors. I guess it's just how I'm built.:)

Warnings are output to stderr. Personally I just do this: make > /dev/null

All that you see after that are warnings and errors.

When I build a program with make, the warnings are very easy to spot. While you do, without warnings, see a bunch of text fly through the screen, all of that text looks incredibly simmilar. Warnings (and errors) stick out in the wall of text.

I guess we've just had different experiences. I can say from experience, without a doubt, that I could not possibly pick out a warning among hundreds of compile/link commands.

Now, if dependencies were in order, and I'd just made a small change to a single file, and had previously built the project successfully, I'm sure I could probably catch a single warning. That's a lot of assumptions to work from. I prefer to let the build fail.

I'd compare it to disabling the snooze button.

> Regarding the author's specific complaint--unused variables--I find that it's quite simple to comment out the declaration

But then you have commented out code potentially forgotten about and checked in and no warning. That's the problem with universally enforcing a rule. Circumventing the rule is usually messier than just breaking it.

I guess I don't understand your complaint. I'm not talking about commenting out huge swaths of code to avoid warnings. And I'm certainly not advocating committing such code. (Or, let me be more clear, I'm not advocating publishing such code. I think it's fine to commit it to a local branch, but the code should be clean by the time it's merged to a public branch.)

But, if you've prematurely declared a variable and find it's throwing a warning, I see no issue with temporarily commenting out the declaration. The only downside I can think of is someone accidentally commits a single-line, commented out variable declaration.

I can say I rarely run into this specific problem. I tend to use variables once they're declared. It's possible my development style is just different. If I found this to be a big problem, I probably would disable the warning for debug builds.

I've had this sort of problem quite a bit, but it probably does depend on programming style. If you use a lot of temporary variables rather than anonymous subexpressions (this is somewhat common among people who use a debugger a lot, and some compilers seem to prefer SIMD code to look like this) then it's very easy for one commented-out line to turn into a whole pile of unused variable warnings that slowly fan out as you "fix" each one in turn (because many expressions simply combine two variables that themselves only exist to be inputs for that expression, and so on in turn). This is terribly galling if you're only commenting something out as a quick (or not, as it turns out...) sanity check while you're trying to debug something.

All in all, warnings-as-errors seemed to me like a bum deal. People who don't fix their warnings without warnings-as-errors can't generally be relied on to fix them properly; people who do fix their warnings would have fixed them anyway; everybody is annoyed at some point.

In fact, I am actually becoming annoyed just thinking about it again ;)

And I'm annoyed when there are hundreds of innocuous warnings. In that case I have to mentally track the warning count so I know when I've incremented it.

Someone who can't fix a warning properly probably isn't a very good coder to begin with. I'd say you're hosed no matter what. :P

I understand you problem with lots of temporary variables. It's not a situation I've encountered. It's certainly something that might make me reassess my position should I encounter it.

> The only downside I can think of is someone accidentally commits a single-line, commented out variable declaration.

Yeah, that's the sort of thing I was thinking of. Or empty method implementations, or dummy return values, or whatever.

I guess my point is just that if it's more convenient to do something else before fixing an issue, then it's better to have a warning reminding you to fix it than to not. And if you're not going to circumvent the error, you're probably not going to ignore the warnings either.

Reading your other comment, you mentioned working with make. The advantage I mentioned only really applies in IDEs.

I find it horrifying how many developers are perfectly happy having warnings in their code.

On the projects I manage, warnings are unacceptable, and treated as errors. We will not release an update until it builds without warnings.

This post has made me visit one of my large project's warnings. There are two that I can't seem to be rid of:

Using NS_REQUIRES_NIL_TERMINATION on a var args Objective-C method seems to cause a warning "Attributes on method implementation and its declaration must match" — despite both the declaration and implementation being exactly the same.

Using uniqueIdentifier in debug builds (for TestFlight) triggers an API deprecation warning. Despite being OK to use for non-App Store iOS apps.

The author just retweeted a link to this header file to enable Clang warnings using #pragma's https://github.com/macmade/SeriousCode https://twitter.com/macmade/status/328219581879558144

I find apples compiler seems to change its mind on what is a warning with every single version, which in turn made me less interest in removing every single one of them (especially when you use third party stuff - unity3d seems to spit out a bunch of warnings right now).

I never do -Wall and -Wextra. Why? Because too many of clang's warning switches have names that have little to do with what they actually warn about. One in particular has to do with it finding duplicate selectors in different classes. I can never remember what it's called, but it's very annoying when you need to find it to disable it. Even worse, when you disable that particular flag, it disables a whole bunch of other actually useful warnings as well!

You also DON'T want to do -Wall and -Wextra along with -Werror. Why? Because when a later version of the compiler gets smarter and puts in more warnings, suddenly your (working) code won't compile anymore! That would go over very poorly in a CI system or an open source library! Your "future proofing" has just ensured that sometime down the road (and likely at an inconvenient time), your project is guaranteed to break!

This is so horribly wrong.

Firstly, when clang warns you of an error, it tells you the switch it uses to highlight that error, the disabling flag is then "-Wno-$switch" (or simply use a clang pragma to disable the warning: http://stackoverflow.com/questions/7017281/performselector-m...)

Secondly, the errors reported by -Wall and -Wextra are likely to be program bugs / bugs further down the line.

Thirdly: I upgraded my compiler on my CI system, I'd damn well want to know about new errors!

"I can never remember what it's called, but it's very annoying when you need to find it to disable it."

These days, clang will tell you what a warning is called any time it gives you one. If you ever need to disable a warning, make it happen (which you probably already did, otherwise why would you need to disable it?) and then just read the error message to see what flag to use to disable it.

What is wrong with breaking the build when the underlying assumptions change? I consider this a good thing. My initial assertion that many warnings are latent errors (bugs) implies that the most inconvenient time is when the product is in the hands of users.

I have another guideline that I frequently apply: Don't update your tools if you're close to cutting a new release. This mitigates the risk of unexpected build issues a the worst possible time.

Whenever I am involved in build setups for C or C++ projects, -Wall, -Werror and static analysis are always part of the build.

It is the only sane way to give C and C++ the same strong typing that other languages enjoy since birth.

Quite useful in projects where due costs, most developers are not that experienced.

I am yet to do a Objective-C project, but I would use the same approach.

You can set the warnings to only appear on debug builds. Would that fix the CI issue?

Applications are open for YC Winter 2018

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact