Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-10257: Fix compiler warnings in afw #250

Merged
merged 8 commits into from Jun 23, 2017
Merged

DM-10257: Fix compiler warnings in afw #250

merged 8 commits into from Jun 23, 2017

Conversation

kfindeisen
Copy link
Member

This PR eliminates all but one compiler warning (unused fits::{}::getFormatCode(int8_t)) when building afw with Ubuntu+GCC and MacOS+Clang. Justifications for individual changes are included in the commit messages.

During the MacOS port a few unrelated clang-format changes were made because of the mismatch in clang-format versions between Ubuntu and MacOS. @parejkoj and I allowed them to get committed on the grounds that we will probably standardize on clang-format 5 anyway.

Most of the warnings in GaussianProcess.cc were patched with
on-the-spot casts. While changing the internal members to unsigned
makes more sense a priori, the current code uses -1 as a null value,
and it is very difficult to maintain KdTree's class invariants during
the conversion. It may be less work to just replace the implementation
of KdTree with an object-oriented rather than array-oriented
implementation.
fits::{}::getFormatCode(int8_t) is unused, but has been left in
because removing it would silently break code if a need for int8_t
appeared later. Unfortunately, GCC's support for locally ignoring
warnings is broken, so there's no way to mark the code as acceptable.
@kfindeisen kfindeisen requested a review from r-owen June 23, 2017 00:35
Copy link
Contributor

@r-owen r-owen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Two trivial suggestions

{std::make_pair("PSF_FLUX", "slot_PsfFlux"), std::make_pair("AP_FLUX", "slot_ApFlux"),
std::make_pair("INST_FLUX", "slot_InstFlux"), std::make_pair("MODEL_FLUX", "slot_ModelFlux"),
std::make_pair("CALIB_FLUX", "slot_CalibFlux"), std::make_pair("CENTROID", "slot_Centroid"),
std::make_pair("SHAPE", "slot_Shape")}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please run clang-format on this file. I found it results in minor but helpful improvements.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the weird brace alignment was from clang-format 5... (@parejkoj can confirm)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that came from saving it in sublimetext with clang-format version 5.0.0 (tags/google/stable/2017-03-17). What version do you have, @r-owen ?

Copy link
Contributor

@r-owen r-owen Jun 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree the braces are weird. That's why I ran clang-format on the file (I guessed the braces were clang-format's fault and I wanted to check that). That confirmed by suspicions, but I was surprised when some other part of the file got reformatted (for the better, I think, though that's not very relevant).

So I suggest reformatting the whole file so all of it is in standard clang-format 5 format (ditto for any other C++ files you touched).

I am running 5.0.0 installed using Homebrew. Here is my config ~/.clang-format which I believe is LSST standard:

Language: Cpp
BasedOnStyle: Google
ColumnLimit: 110
IndentWidth: 4
AccessModifierOffset: -4
SortIncludes: false # reordering may break existing code
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My format file looks the same as yours, except with a --- as the first line, and ... as the last line (copied directly from the dev-guide).

I just re-ran clang-format outside of sublimeText, and it didn't change the file as checked-in. My version is also installed via homebrew.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must be user error on my part. I just reformatted again and although Sublime Text claims the file changed, this time there are no visible changes (last time there were, and I'm not sure why).

@@ -157,7 +157,7 @@ ::gsl_interp_type const *styleToGslInterpType(Interpolate::Style const style) {
case Interpolate::UNKNOWN:
throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
"I am unable to make an interpolator of type UNKNOWN");
case Interpolate::NUM_STYLES:
default:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a default clause is good, but removing the NUM_STYLES clause worries me. Some compilers warn if your case statements do not cover all cases (and I'm surprised clang did not).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect a compiler to warn you if you have redundant cases in front of your default, but I guess I could add it back in and see what happens.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, neither compiler cares. I'll leave it in.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cares. If you use default the compiler can't check for missing enums. NUM_STYLES is probably there as it's in the enum and the compiler can/should whine if it's omitted.

Copy link
Contributor

@r-owen r-owen Jun 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that ending with a default case is considered an important part of defensive programming, because even in C++ it is possible to provide illegal values (e.g. by casting).

I'm disappointed that compilers don't warn about missing values when a default clauses is included.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without a default clause GCC gives a warning about falling through to the end of the function even when every constant is mentioned (despite also doing the check you mentioned).

I think I have an idea that will satisfy both rules, let me check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I turns out recent gcc can warn in this situation, but it requires a flag: https://stackoverflow.com/questions/5402745/gcc-switch-on-enum-retain-missing-warning-but-use-default

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about:

     case Interpolate::NUM_STYLES:
          throw LSST_EXCEPT(pex::exceptions::LogicError,
                            str(boost::format("You can't get here: style == %") % style));
     default:
          abort();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a workaround, I've removed the default and added an exception after the switch. That lets GCC check that the cases are complete (and yes, I tested it) without complaining about reaching the end of the function. It's clunky, but I think it's the only way we can satisfy both constraints at the moment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Russell's suggestion relies on #pragma GCC diagnostic, which is broken at the moment. It would certainly be my preferred solution otherwise. 😞

kfindeisen and others added 6 commits June 23, 2017 11:44
While the clang warning is a bug (shared_ptr::operator* is const, and
therefore has no side effects), in most cases the use of typeid merely
served to slow down the program. The code has been rearranged to
minimize use of RTTI.
clang-format 5 on save
Remove fabs warnings for int and unsigned templates

clang-format 5 on save
clang-format 5 on save
@RobertLuptonTheGood
Copy link
Member

RobertLuptonTheGood commented Jun 23, 2017 via email

@kfindeisen
Copy link
Member Author

Good idea, but no, GCC still doesn't like the original function structure. (Also, Interpolate::Style is used as an integer quite frequently.)

The new current version (as of 30 minutes ago) allows static testing, so I propose we live with it.

@@ -161,6 +161,9 @@ ::gsl_interp_type const *styleToGslInterpType(Interpolate::Style const style) {
throw LSST_EXCEPT(pex::exceptions::LogicError,
str(boost::format("You can't get here: style == %") % style));
}
// don't use default statement to let compiler check switch coverage
throw LSST_EXCEPT(pex::exceptions::LogicError,
str(boost::format("You can't get here: style == %") % style));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can't ever get there, this is a programming error, and therefore an abort() is more appropriate than an exception.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An abort would cause the entire Stack to crash, with no explanation, in the middle of processing. It certainly wouldn't make it obvious that the programmer forgot to include an enum.

There is simply no justification for calling abort() in low-level functions in modern code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is exactly the point! You want the entire stack to crash (with a core dump) because you're in a completely bad situation that cannot be recovered from. If you throw an exception it might be caught and ignored, which makes it so much harder to know there's a problem at all, let alone debug it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will say that I've had this same argument with folks before. I'm firmly on @kfindeisen's side -- I want a proper stack trace when something goes wrong, so I always thrown an exception. But there are certainly those in the project who are prefer C++ assert for this situation. I don't think it'll get resolved at our level, and rather than bring in the big guns for such a small and helpful ticket, I suggest we keep what @kfindeisen has done and move on.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...If for no other reason than because it is the minimal change from what we had already!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can get "a proper stack trace" from the core dump, or from re-running under a debugger. Throwing an exception does not guarantee that you're going to get a stack trace at all, or ever even notice that there's something horribly wrong.

It's absolutely essential when we know that the system is in an inconsistent state (e.g., smashed stack, memory corruption) that we not attempt to push forward and make things worse and undebuggable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed for memory corruption. That is not the concern here. A simple cast can get you this issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth doing even for "a simple cast" error, but I give up.

@kfindeisen kfindeisen merged commit 9668c66 into master Jun 23, 2017
@kfindeisen kfindeisen deleted the tickets/DM-10257 branch August 22, 2018 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants