-
Notifications
You must be signed in to change notification settings - Fork 10
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
Check for unused usage #35
Comments
This is quite a knotty problem. Firstly, anything which can be made "public" may appear in the "only" list. According to the Fortran standard this means: "Each use-name shall be the name of a named variable, procedure, derived type, named constant or namelist group." The first problem is that this definition includes The next thing to do is confirm my suspicion that local definitions can override something which has been brought in by a "use". This makes sense as usage is really just a scope trick. It's like importing a bunch of declarations at the point where the Talking of scope, a definition can appear at module scope, type scope, procedure scope or block scope. "Use" statements may appear at module scope and procedure scope. |
Potential solutions include a depth-first tree walk which bubbles unused names to the level above. At the lowest level in the scope tree all used names are noted in a set. This set is pruned by the definitions at that level, then passed up. The next level up adds usages then resolves everything declared at that level. This process iterates over the whole tree. When a "use" is encountered the "only" list can be compared against the set of outstanding names. Anything appearing in the "only" list but not the outstanding names list is unused. Everything which appears in both is removed from the outstanding list. |
A top-down approach would also work. Descend the scope tree noting every declaration (including usage) in a list of sets, one list for each level in the scope tree. For each reference to a name, find it in the list of sets starting at the "bottom" and working up, mark the first occurrence found as having been "hit". It needs to remain so additional references do not go further up the list. After the whole scope tree has been traversed any usage declarations which remain un-"hit" have not been used. |
Here is a little example code which might form the basis of testing. |
I just had a little go with your example code and found fparser doesn't understand block statements. A minimal example results in a syntax error and no tree is created. Probably something to bring up with the fparser team. |
Is it worth simplifying the requirement? Really, we care most if an unused Therefore, we can parse once to collect all things that are used and then parse again to make sure they are all called at least once. If something is declared twice in two scoping units, but only referenced in one, it's not terribly important. We would miss issues where two scoping units use something with the same name but in different modules, but that feels like a rare scenario that a sensible coder ought to resolve by locally renaming at least one of them. Perhaps a separate rule could require that identical names are locally renamed so all names are unique. Other issues (an item used but not called in one scoping unit and called but not used in another) would be identified by a compile failure. |
Make sure that everything listed in the "only" list of a "use" statement is, in fact, used. Obviously this can only work where there is an "only" list.
The text was updated successfully, but these errors were encountered: