File: analyze_gfortran_warnings.py

package info (click to toggle)
cp2k 6.1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 204,532 kB
  • sloc: fortran: 835,196; f90: 59,605; python: 9,861; sh: 7,882; cpp: 4,868; ansic: 2,807; xml: 2,185; lisp: 733; pascal: 612; perl: 547; makefile: 497; csh: 16
file content (115 lines) | stat: -rwxr-xr-x 4,863 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# author: Ole Schuett

import re
import sys
from os import path

blas_re = re.compile("[SDCZ]"
                     +"(ROTG|ROTMG|ROT|ROTM|SWAP|SCAL|COPY|AXPY|DOT|DOTU|DOTC" #level 1
                     +"|GEMV|GBMV|HEMV|HBMV|HPMV|SYMV|SBMV|SPMV|TRMV|TBMV|TPMV|TRSV" # level 2
                     +"|TBSV|TPSV|GER|GERU|GERC|HER|HPR|HER2|HPR2|SYR|SPR|SYR2|SPR2"
                     +"|GEMM|SYMM|HEMM|SYRK|HERK|SYR2K|HER2K|TRMM|TRSM"  # level 3
                     +"|LANGE|LARNV|LAMCH|NRM2|CNRM2|ZNRM2|DSCAL)") # aux

lapack_re = re.compile("ILAENV|"
                       +"([SDCZ]" + "(BD|DI|GB|GE|GG|GT|HB|HE|HG|HP|HS|OP"
                       +"|OR|PB|PO|PP|PT|SB|SP|ST|SY|TB|TG|TP|TR|TZ|UN|UP)"
                       +"(BAK|BAL|BRD|CON|EBZ|EDC|EIN|EQR|EGR|EQU|EQZ|ERF|EVC"
                       +"|EXC|GBR|GHR|GLQ|GQL|GQR|GRQ|GST|GTR|HRD|LQF|MBR|MHR"
                       +"|MLQ|MQL|MQR|MRQ|MRZ|MTR|QLF|QPF|QRF|RFS|RQF|RZF|SDC"
                       +"|SEN|SJA|SNA|SQR|SVP|SYL|TRD|TRF|TRI|TRS"
                       +"|SDD|EV|GV|SV|BS2D|BR2D|LS))")

warning_re = re.compile(".*[Ww]arning: (.*)")


#===============================================================================
def main():
    if(len(sys.argv) < 2):
        print("Usage: analyse_gfortran_warnings.py <warn-file-1> ... <warn-file-N>")
        print("       This tool checks the given stderr output from gfortran for violations of the coding conventions.")
        print("       For generating the warn-files run gfortran with as all warning flags and redirect the output to a file.")
        print('       This can be achieved by putting "FCLOGPIPE = 2>$(notdir $<).warn" in the cp2k arch-file.')
        sys.exit(1)

    files = sys.argv[1:]
    for fn in files:
        check_warnings(fn)

#===============================================================================
def check_warnings(fn):
    content = open(fn).read()

    lines = content.split("\n")
    loc = loc_short = ""
    for i, line in enumerate(lines):
        if(len(line)==0): continue

        # line directives issues by gcc directly
        # we ignore non-absolut paths, because they point to indermediate fypp output
        if(line[0]=="/" and line[-1]==":"):
            loc = line.rsplit(":")[0].strip()
            loc_short = path.basename(loc)
            continue

        # fypp line directives that leaked through as part of warning messages
        if(line.startswith(' # 1 "')):
            loc = line[6:-1]
            loc_short = path.basename(loc)
            continue

        if(loc.endswith("include/fftw3.f")): continue # an external file

        m = warning_re.match(line)
        if(not m): continue # we are only looking for warnings
        warning = m.group(1)

        # we ignore these warnings
        if("-Wmaybe-uninitialized" in warning): continue
        if("Creating array temporary" in warning): continue
        if("quality comparison" in warning): continue
        if("Unused" in warning):
            if("'error'" in warning): continue
            if("'routinep'" in warning): continue
            if(loc_short == "cp_common_uses.f90"): continue
        if("defined but not used" in warning): continue
        if("Removing call to function" in warning): continue
        if("Conversion from" in warning): continue
        if("Non-significant digits in 'REAL(8)'" in warning): continue
        if("CHARACTER expression" in warning and "truncated" in warning): continue
        if("POINTER-valued function appears on right-hand side" in warning): continue
        if("style of line directive is a GCC extension" in warning): continue

        # ok this warning we should handle
        if("called with an implicit interface" in warning):
            parts = warning.split()
            assert(parts[0] == "Procedure")
            routine = parts[1].strip("'").upper()
            if(may_call_implicit(loc, routine)): continue
            print("%s: Routine %s called with an implicit interface."%(loc_short, routine))
        else:
            print("%s: %s"%(loc_short, warning)) # unknown warning, just output

#===============================================================================
def may_call_implicit(loc, routine):
    if(blas_re.match(routine)):
        return(True)  # BLAS calls are allowed everywhere
    if(lapack_re.match(routine)):
        return(True) # Lapack calls are allowed everywhere

    pkg = path.dirname(loc)
    manifest_fn = pkg+"/PACKAGE"
    manifest = eval(open(manifest_fn).read())
    if(not manifest.has_key("implicit")): return(False)

    return(re.match(manifest["implicit"], routine))

#===============================================================================
if(len(sys.argv)==2 and sys.argv[-1]=="--selftest"):
    pass #TODO implement selftest
else:
    main()
#EOF