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

Quiet compiler warnings for registry.exe #1858

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from

Conversation

DWesl
Copy link
Contributor

@DWesl DWesl commented May 8, 2023

Quiet the compiler warnings in registry.exe

TYPE: bug fix

KEYWORDS: compiler warnings, snprintf, initial values, string length

SOURCE: "Daniel Wesloh (Pennsylvania State University Department of Meteorology and Atmospheric Science)"

DESCRIPTION OF CHANGES:
Problem:
Generally or specifically, what was wrong and needed to be addressed?
A few years ago, registry.exe was segfaulting while compiling WRF. I enabled every compiler warning for that build process I could find, and tried to fix every one I saw. The problem ended up being insufficient stack space (fix merged a few years ago), but fixing the warnings probably won't hurt.

Solution:
What was down algorithmically and in the source code to address the problem?

  • make sure string buffers are large enough for the contents put in them
  • don't use larger types than necessary (i.e. use short instead of int for numbers in the 300--16,000 range, so printf knows that five characters will be enough)
  • Specify maximum lengths to copy using snprintf and friends
  • Make sure all variables are initialized.

ISSUE: None

LIST OF MODIFIED FILES: list of changed files

M       configure
M       doc/README.cygwin.md
M       inc/streams.h
M       tools/Makefile
M       tools/data.h
M       tools/fseek_test.c
M       tools/gen_allocs.c
M       tools/gen_args.c
M       tools/gen_config.c
M       tools/gen_defs.c
M       tools/gen_interp.c
M       tools/gen_irr_diag.c
M       tools/gen_scalar_indices.c
M       tools/gen_streams.c
M       tools/gen_wrf_io.c
M       tools/misc.c
M       tools/protos.h
M       tools/reg_parse.c
M       tools/registry.c
M       tools/registry.h
M       tools/set_dim_strs.c
M       tools/sym.c
M       tools/sym.h
M       tools/symtab_gen.c
M       tools/type.c

TESTS CONDUCTED:

  1. Do mods fix problem? How can that be demonstrated, and was that test conducted?
  2. Are the Jenkins tests all passing?
    • I have no idea how to run those

RELEASE NOTE: Eliminate some compiler warnings when building registry.exe

@DWesl DWesl requested review from a team as code owners May 8, 2023 16:49
@weiwangncar
Copy link
Collaborator

@DWesl It looks like the compilation is failed for all of the tests. Our regression tests are run using gfortran compiler. Here is a particular error (also see the attached file):

make[2]: Entering directory '/wrf/WRF/tools'
gcc -DIWORDSIZE=4 -DMAX_HISTORY=25 -DNMM_CORE=0 -c -g registry.c
registry.c:7:11: fatal error: io.h: No such file or directory
7 | # include <io.h>
| ^~~~~~

output_3.txt

@DWesl
Copy link
Contributor Author

DWesl commented May 9, 2023

Interesting. My own tests all used GFortran, so it's likely a Cygwin/Linux difference rather than a compiler one. I set up guards so the #include <io.h> should only get seen on Windows and Cygwin and not on Linux, so hopefully that problem goes away.

@weiwangncar
Copy link
Collaborator

OK, now our regression tests have passed:

Test Type              | Expected  | Received |  Failed
= = = = = = = = = = = = = = = = = = = = = = = =  = = = =
Number of Tests        : 23           24
Number of Builds       : 60           57
Number of Simulations  : 158           150        0
Number of Comparisons  : 95           86        0

Failed Simulations are: 
None
Which comparisons are not bit-for-bit: 
None

@DWesl
Copy link
Contributor Author

DWesl commented May 10, 2023

OK, now our regression tests have passed:

As have mine on Cygwin (with #1812)

@DWesl
Copy link
Contributor Author

DWesl commented Aug 13, 2023

Am I missing anything for this PR?

@weiwangncar
Copy link
Collaborator

@islas Are any of the changes proposed here in conflict with anything you've been working on?

@islas
Copy link
Collaborator

islas commented Oct 2, 2023

@weiwangncar Nope, no conflicts should arise from our respective changes in registry

@weiwangncar
Copy link
Collaborator

@islas Great! Should we consider this in develop or for 4.5.2?

@islas
Copy link
Collaborator

islas commented Oct 2, 2023

I'd say this would be a nice-to-have if we can get it in, but not critical.

@weiwangncar
Copy link
Collaborator

@islas Thanks. We can leave it on the develop branch.

@weiwangncar weiwangncar changed the base branch from master to develop October 2, 2023 20:15
tools/gen_allocs.c Outdated Show resolved Hide resolved
strcat( line,piece );
}
strcat( line," /)\n" );
fprintf( fp_inc,line );
fprintf( fp_inc," \n");

for( i = 0; i < nChmOpts,rxt_cnt[i] > 0; i++ ) {
for( i = 0; /*i < nChmOpts &&*/ rxt_cnt[i] > 0; i++ ) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems like this is relying on rxt_cnt to be default initialized to zero. I'm not too sure what it is used for, but given that all other loops use nChmOpts to specify number of indices into rxt_cnt, keeping this check seems prudent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The old version was ignoring the result of the nChmOpts comparison. Are you suggesting that check be included in the for-loop exit condition?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah! You're correct, I forgot that this use of the , operator is nulling and not &&

I'd imagine that the original intent was to have it included via && given the other loops. Maybe @weiwangncar or someone else with historic knowledge on this section of the Registry can chime in. Otherwise, as long as tests agree, I think that check should be there

Copy link
Contributor Author

@DWesl DWesl Nov 4, 2023

Choose a reason for hiding this comment

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

Changed to the suggested form. I'd still like to get an opinion from someone who knows this bit of the code better than me.

tools/registry.c Show resolved Hide resolved
tools/registry.c Outdated Show resolved Hide resolved
tools/registry.c Outdated Show resolved Hide resolved
tools/sym.c Outdated Show resolved Hide resolved
Copy link
Contributor Author

@DWesl DWesl left a comment

Choose a reason for hiding this comment

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

A few magic constants I didn't catch earlier, plus some possibly-premature optimizations.


if ( p->ntl > 1 ) { sprintf(tag,"_2") ; sprintf(tag2,"_%d", use_nest_time_level) ; }
else { sprintf(tag,"") ; sprintf(tag2,"") ; }
else { tag[0] = '\0'; tag2[0] = '\0'; }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

sprintf will likely be clearer, and the compiler may notice this optimization anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alternately, strcpy/strncpy

@@ -200,7 +200,7 @@ gen_nest_interp1 ( FILE * fp , node_t * node, char * fourdname, int down_path ,
if ( nest_mask & down_path )
{
if ( p->ntl > 1 ) { sprintf(tag,"_2") ; sprintf(tag2,"_%d", use_nest_time_level) ; }
else { sprintf(tag,"") ; sprintf(tag2,"") ; }
else { tag[0] = '\0'; tag2[0] = '\0'; }
Copy link
Contributor Author

@DWesl DWesl Jan 2, 2024

Choose a reason for hiding this comment

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

sprintf or strcpy will likely be clearer, and the compiler might notice this optimization anyway.

@@ -130,7 +130,7 @@ else if ( down_path[ipath] == FORCE_DOWN ) { sprintf(halo_id,"HALO_FORCE_DOWN")
else if ( down_path[ipath] == INTERP_UP ) { sprintf(halo_id,"HALO_INTERP_UP") ; }
else if ( down_path[ipath] == SMOOTH_UP ) { sprintf(halo_id,"HALO_INTERP_SMOOTH") ; }
sprintf(halo_define,"80:") ;
sprintf(halo_use,"") ;
halo_use[0] = '\0' ;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

sprintf may be clearer, and the compiler may still notice the optimization.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or strcpy, since this isn't using any of the formatting features.

tools/gen_defs.c Outdated Show resolved Hide resolved
tools/gen_config.c Outdated Show resolved Hide resolved
tools/reg_parse.c Outdated Show resolved Hide resolved
@@ -256,7 +275,7 @@ pre_parse( char * dir, FILE * infile, FILE * outfile )
if ( !strcmp( tokens[F_USE] , tracers[i] ) ) found = 1 ;
}
if ( found == 0 ) {
sprintf(tracers[ntracers],tokens[F_USE]) ;
snprintf(tracers[ntracers], 100, tokens[F_USE]) ;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Definition on line 89; should this be another magic constant?

Comment on lines -7 to 11
#else
#endif
# include <sys/time.h>
# include <sys/resource.h>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suspect these two headers are still unavailable on Windows; the others might be.

@@ -1,6 +1,12 @@
#ifndef REGISTRY_H
#include <stdlib.h>
#include <ctype.h>
#include <sys/unistd.h>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This might also be unavailable on Windows.

@@ -157,7 +159,8 @@ main( int argc, char *argv[], char *env[] )
sprintf( fname_wrk,"%s/Registry_irr_diag",dir ) ;
}
// fprintf(stderr,"Registry tmp file = %s\n",fname_wrk);
sprintf(command,"/bin/cp %s %s\n",fname_in,fname_wrk);
/* we should be able to implement this using posix_spawn */
sprintf(command,"/bin/cp \'%s\' \'%s\'\n",fname_in,fname_wrk);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will still break if the filename includes apostrophes, but I think that's unlikely enough to not try re-implementing Python's shlex.quote.

@weiwangncar
Copy link
Collaborator

@DWesl The compilation failed in our regression test. If you need to see the output, let me know.

@weiwangncar
Copy link
Collaborator

The regression test results from the last commit:

Test Type              | Expected  | Received |  Failed
= = = = = = = = = = = = = = = = = = = = = = = =  = = = =
Number of Tests        : 23           24
Number of Builds       : 60           57
Number of Simulations  : 158           150        0
Number of Comparisons  : 95           86        0

Failed Simulations are: 
None
Which comparisons are not bit-for-bit: 
None

@weiwangncar
Copy link
Collaborator

@islas Is this ready for approval?

@islas
Copy link
Collaborator

islas commented Jan 24, 2024

@weiwangncar I think @DWesl has a lot of self-marked revisions they are still going through. Is that correct?

@DWesl
Copy link
Contributor Author

DWesl commented Jan 26, 2024

I completed all the simple work I noticed on a second passthrough. There's a few places where I would like feedback on style.

@DWesl
Copy link
Contributor Author

DWesl commented Jan 26, 2024

Something that should be noted before the final merge: I accidently added a Cygwin workflow in GitHub actions; I'm not sure if the maintainers want to keep that in or out of the main repository.

EDIT: I added the entire "Fix Cygwin compile" PR to this one. Should I rebase the branch to drop those changes? Or just edit them out and let the merge sort out differences?

@weiwangncar
Copy link
Collaborator

@DWesl Thanks for removing the Cygwin changes!
@islas Are we ok with this PR?

@islas
Copy link
Collaborator

islas commented Feb 1, 2024

I still see some Cygwin changes to configure and the workflow. I'm unsure if that is something we will want to add, though having a test would be incredibly helpful. That content & discussion might be more suited to a Cygwin-specific PR

There might be more I wanted to add, but I don't remember.
I'll have to add those the way I did the first time,
compiling with -Werror until it works.
This pass is almost exclusively focused on the registry.
I'll have a few more for Fortran once I figure out how.

Inspiration: registry was segfaulting, so I tried fixing the warnings
in case it was one of those.  It didn't work, but it's worth doing
regardless.
Change compile flags back to what they were before.
Guard io.h #include to avoid Linux compilation failures.
Given how much space this provides at the moment, this had better not
run over.
Most likely the better solution is to look up functions
to copy or delete files directly.
I'm not sure where to look for those,
but I'm pretty sure they're not in the C standard.
I pushed it to another branch, so a PR version can get some eyes on it.
external/RSL_LITE implements these as int, so they need to be declared with int returns, not void.
Not quite all of them yet, but there's only one other, that one
without an existing named constant.

EDIT: There's about seventy left: I'll have to go through those again.
I think there's a way to pass this as a parameter to snprintf instead, but I don't remember what that is at the moment.
I looked up how to do this.  Apparently you just stick a star for the width and put the variable with the width before the variable you want to have that width.
grep -E -e '\[[[:digit:]]{2,}\]' *.[CcHhFf]*
@DWesl DWesl force-pushed the quiet-compiler-warnings-registry branch from 1d09961 to 4ba1aab Compare February 8, 2024 17:47
Lots of unused variables, but I should be able to leave those for a bit.
Unused parameters would be a pain, so I'm leaving those.
@DWesl
Copy link
Contributor Author

DWesl commented Feb 11, 2024

I split off the remaining Cygwin-specific fixes to DWesl#5. This should be just the bits that address warnings, with comments on the bits I thought might be controversial.

I wanted to make it a short to save space in the strings based on this, but given the push to optimize for clarity that's less relevant.
@weiwangncar
Copy link
Collaborator

@DWesl This PR has code conflicts with what is in the latest repository. Can you resolve these conflicts while preserving the latest change in the repository?

@DWesl
Copy link
Contributor Author

DWesl commented Feb 24, 2024

There's a number of places that change !(p->node_kind & BIT_MASK) to (!p->node_kind) & BIT_MASK, which is basically always going to return false. Could you point me to the PR that made that change and the reasoning for it? My inclination otherwise would be to revert that change or to make it (~p->node_kind & BIT_MASK).

@DWesl
Copy link
Contributor Author

DWesl commented Feb 24, 2024

Apparently that's #1942, which also attempted to fix warnings, in this case a warning that ! p->node_kind & BIT_MASK wasn't doing what was most likely wanted (extracting the bits corresponding to the mask then inverting the result), but was instead applying a logical-not to a bit sequence (which results in either 1 or 0) and then applying the bit mask (here 8, so the result would always be zero). Should I go through and change those to be either a bitwise-invert or apply the parentheses implied by the warning (so the bit-mask gets applied before the logical-not)?

The other option would be to just delete the conditional, but the comment implies there's a point to it. I just asked on that PR for clarification of what I should do with those cases.

I made nChmOpts a short int to keep buffer size down.
Given the change to named constants, this is likely irrelevant.

On the other hand, it may currently max out at five.
@DWesl
Copy link
Contributor Author

DWesl commented Mar 2, 2024

Discussion resolved there, conflicts resolved here: I kept the bit-mask then logical-not I already had.

@DWesl
Copy link
Contributor Author

DWesl commented Apr 8, 2024

Should I try to squash the changes into fewer commits?

@weiwangncar
Copy link
Collaborator

@islas Can you see if this PR can be accepted?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants