[TableGen] Sort pattern predicates before concatenating into a string so that differe...
[oota-llvm.git] / utils / lint / cpp_lint.py
1 #!/usr/bin/python
2 #
3 # Checks C++ files to make sure they conform to LLVM standards, as specified in
4 # http://llvm.org/docs/CodingStandards.html .
5 #
6 # TODO: add unittests for the verifier functions:
7 # http://docs.python.org/library/unittest.html .
8
9 import common_lint
10 import re
11 import sys
12
13 def VerifyIncludes(filename, lines):
14   """Makes sure the #includes are in proper order and no disallows files are
15   #included.
16
17   Args:
18     filename: the file under consideration as string
19     lines: contents of the file as string array
20   """
21   lint = []
22
23   include_gtest_re = re.compile(r'^#include "gtest/(.*)"')
24   include_llvm_re = re.compile(r'^#include "llvm/(.*)"')
25   include_support_re = re.compile(r'^#include "(Support/.*)"')
26   include_config_re = re.compile(r'^#include "(Config/.*)"')
27   include_system_re = re.compile(r'^#include <(.*)>')
28
29   DISALLOWED_SYSTEM_HEADERS = ['iostream']
30
31   line_num = 1
32   prev_config_header = None
33   prev_system_header = None
34   for line in lines:
35     # TODO: implement private headers
36     # TODO: implement gtest headers
37     # TODO: implement top-level llvm/* headers
38     # TODO: implement llvm/Support/* headers
39
40     # Process Config/* headers
41     config_header = include_config_re.match(line)
42     if config_header:
43       curr_config_header = config_header.group(1)
44       if prev_config_header:
45         if prev_config_header > curr_config_header:
46           lint.append((filename, line_num,
47                        'Config headers not in order: "%s" before "%s"' % (
48                          prev_config_header, curr_config_header)))
49
50     # Process system headers
51     system_header = include_system_re.match(line)
52     if system_header:
53       curr_system_header = system_header.group(1)
54
55       # Is it blacklisted?
56       if curr_system_header in DISALLOWED_SYSTEM_HEADERS:
57         lint.append((filename, line_num,
58                      'Disallowed system header: <%s>' % curr_system_header))
59       elif prev_system_header:
60         # Make sure system headers are alphabetized amongst themselves
61         if prev_system_header > curr_system_header:
62           lint.append((filename, line_num,
63                        'System headers not in order: <%s> before <%s>' % (
64                          prev_system_header, curr_system_header)))
65
66       prev_system_header = curr_system_header
67
68     line_num += 1
69
70   return lint
71
72
73 class CppLint(common_lint.BaseLint):
74   MAX_LINE_LENGTH = 80
75
76   def RunOnFile(self, filename, lines):
77     lint = []
78     lint.extend(VerifyIncludes(filename, lines))
79     lint.extend(common_lint.VerifyLineLength(filename, lines,
80                                              CppLint.MAX_LINE_LENGTH))
81     lint.extend(common_lint.VerifyTabs(filename, lines))
82     lint.extend(common_lint.VerifyTrailingWhitespace(filename, lines))
83     return lint
84
85
86 def CppLintMain(filenames):
87   all_lint = common_lint.RunLintOverAllFiles(CppLint(), filenames)
88   for lint in all_lint:
89     print '%s:%d:%s' % (lint[0], lint[1], lint[2])
90   return 0
91
92
93 if __name__ == '__main__':
94   sys.exit(CppLintMain(sys.argv[1:]))