xref: /llvm-project/clang-tools-extra/unittests/clang-tidy/LLVMModuleTest.cpp (revision b75e7eae17a56a42f6e23f0f11d331ef260a51fe)
1 #include "ClangTidyTest.h"
2 #include "llvm/HeaderGuardCheck.h"
3 #include "llvm/IncludeOrderCheck.h"
4 #include "gtest/gtest.h"
5 
6 using namespace clang::tidy::llvm_check;
7 
8 namespace clang {
9 namespace tidy {
10 namespace test {
11 
12 // FIXME: It seems this might be incompatible to dos path. Investigating.
13 #if !defined(_WIN32)
14 static std::string runHeaderGuardCheck(StringRef Code, const Twine &Filename,
15                                        Optional<StringRef> ExpectedWarning) {
16   std::vector<ClangTidyError> Errors;
17   std::string Result = test::runCheckOnCode<LLVMHeaderGuardCheck>(
18       Code, &Errors, Filename, std::string("-xc++-header"));
19   if (Errors.size() != (size_t)ExpectedWarning.hasValue())
20     return "invalid error count";
21   if (ExpectedWarning && *ExpectedWarning != Errors.back().Message.Message)
22     return "expected: '" + ExpectedWarning->str() + "', saw: '" +
23            Errors.back().Message.Message + "'";
24   return Result;
25 }
26 
27 namespace {
28 struct WithEndifComment : public LLVMHeaderGuardCheck {
29   WithEndifComment(StringRef Name, ClangTidyContext *Context)
30       : LLVMHeaderGuardCheck(Name, Context) {}
31   bool shouldSuggestEndifComment(StringRef Filename) override { return true; }
32 };
33 } // namespace
34 
35 static std::string
36 runHeaderGuardCheckWithEndif(StringRef Code, const Twine &Filename,
37                              Optional<StringRef> ExpectedWarning) {
38   std::vector<ClangTidyError> Errors;
39   std::string Result = test::runCheckOnCode<WithEndifComment>(
40       Code, &Errors, Filename, std::string("-xc++-header"));
41   if (Errors.size() != (size_t)ExpectedWarning.hasValue())
42     return "invalid error count";
43   if (ExpectedWarning && *ExpectedWarning != Errors.back().Message.Message)
44     return "expected: '" + ExpectedWarning->str() + "', saw: '" +
45            Errors.back().Message.Message + "'";
46   return Result;
47 }
48 
49 TEST(LLVMHeaderGuardCheckTest, FixHeaderGuards) {
50   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
51             "#define LLVM_ADT_FOO_H\n"
52             "#endif\n",
53             runHeaderGuardCheck(
54                 "#ifndef FOO\n"
55                 "#define FOO\n"
56                 "#endif\n",
57                 "include/llvm/ADT/foo.h",
58                 StringRef("header guard does not follow preferred style")));
59 
60   // Allow trailing underscores.
61   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n"
62             "#define LLVM_ADT_FOO_H_\n"
63             "#endif\n",
64             runHeaderGuardCheck("#ifndef LLVM_ADT_FOO_H_\n"
65                                 "#define LLVM_ADT_FOO_H_\n"
66                                 "#endif\n",
67                                 "include/llvm/ADT/foo.h", None));
68 
69   EXPECT_EQ("#ifndef LLVM_CLANG_C_BAR_H\n"
70             "#define LLVM_CLANG_C_BAR_H\n"
71             "\n"
72             "\n"
73             "#endif\n",
74             runHeaderGuardCheck("", "./include/clang-c/bar.h",
75                                 StringRef("header is missing header guard")));
76 
77   EXPECT_EQ("#ifndef LLVM_CLANG_LIB_CODEGEN_C_H\n"
78             "#define LLVM_CLANG_LIB_CODEGEN_C_H\n"
79             "\n"
80             "\n"
81             "#endif\n",
82             runHeaderGuardCheck("", "tools/clang/lib/CodeGen/c.h",
83                                 StringRef("header is missing header guard")));
84 
85   EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n"
86             "#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n"
87             "\n"
88             "\n"
89             "#endif\n",
90             runHeaderGuardCheck("", "tools/clang/tools/extra/clang-tidy/x.h",
91                                 StringRef("header is missing header guard")));
92 
93   EXPECT_EQ(
94       "int foo;\n"
95       "#ifndef LLVM_CLANG_BAR_H\n"
96       "#define LLVM_CLANG_BAR_H\n"
97       "#endif\n",
98       runHeaderGuardCheck("int foo;\n"
99                           "#ifndef LLVM_CLANG_BAR_H\n"
100                           "#define LLVM_CLANG_BAR_H\n"
101                           "#endif\n",
102                           "include/clang/bar.h",
103                           StringRef("code/includes outside of area guarded by "
104                                     "header guard; consider moving it")));
105 
106   EXPECT_EQ(
107       "#ifndef LLVM_CLANG_BAR_H\n"
108       "#define LLVM_CLANG_BAR_H\n"
109       "#endif\n"
110       "int foo;\n",
111       runHeaderGuardCheck("#ifndef LLVM_CLANG_BAR_H\n"
112                           "#define LLVM_CLANG_BAR_H\n"
113                           "#endif\n"
114                           "int foo;\n",
115                           "include/clang/bar.h",
116                           StringRef("code/includes outside of area guarded by "
117                                     "header guard; consider moving it")));
118 
119   EXPECT_EQ("#ifndef LLVM_CLANG_BAR_H\n"
120             "#define LLVM_CLANG_BAR_H\n"
121             "\n"
122             "int foo;\n"
123             "#ifndef FOOLOLO\n"
124             "#define FOOLOLO\n"
125             "#endif\n"
126             "\n"
127             "#endif\n",
128             runHeaderGuardCheck("int foo;\n"
129                                 "#ifndef FOOLOLO\n"
130                                 "#define FOOLOLO\n"
131                                 "#endif\n",
132                                 "include/clang/bar.h",
133                                 StringRef("header is missing header guard")));
134 
135   // Fix incorrect #endif comments even if we shouldn't add new ones.
136   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
137             "#define LLVM_ADT_FOO_H\n"
138             "#endif // LLVM_ADT_FOO_H\n",
139             runHeaderGuardCheck(
140                 "#ifndef FOO\n"
141                 "#define FOO\n"
142                 "#endif // FOO\n",
143                 "include/llvm/ADT/foo.h",
144                 StringRef("header guard does not follow preferred style")));
145 
146   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
147             "#define LLVM_ADT_FOO_H\n"
148             "#endif // LLVM_ADT_FOO_H\n",
149             runHeaderGuardCheckWithEndif(
150                 "#ifndef FOO\n"
151                 "#define FOO\n"
152                 "#endif\n",
153                 "include/llvm/ADT/foo.h",
154                 StringRef("header guard does not follow preferred style")));
155 
156   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
157             "#define LLVM_ADT_FOO_H\n"
158             "#endif // LLVM_ADT_FOO_H\n",
159             runHeaderGuardCheckWithEndif(
160                 "#ifndef LLVM_ADT_FOO_H\n"
161                 "#define LLVM_ADT_FOO_H\n"
162                 "#endif // LLVM_H\n",
163                 "include/llvm/ADT/foo.h",
164                 StringRef("#endif for a header guard should reference the "
165                           "guard macro in a comment")));
166 
167   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
168             "#define LLVM_ADT_FOO_H\n"
169             "#endif /* LLVM_ADT_FOO_H */\n",
170             runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n"
171                                          "#define LLVM_ADT_FOO_H\n"
172                                          "#endif /* LLVM_ADT_FOO_H */\n",
173                                          "include/llvm/ADT/foo.h", None));
174 
175   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n"
176             "#define LLVM_ADT_FOO_H_\n"
177             "#endif // LLVM_ADT_FOO_H_\n",
178             runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H_\n"
179                                          "#define LLVM_ADT_FOO_H_\n"
180                                          "#endif // LLVM_ADT_FOO_H_\n",
181                                          "include/llvm/ADT/foo.h", None));
182 
183   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
184             "#define LLVM_ADT_FOO_H\n"
185             "#endif // LLVM_ADT_FOO_H\n",
186             runHeaderGuardCheckWithEndif(
187                 "#ifndef LLVM_ADT_FOO_H_\n"
188                 "#define LLVM_ADT_FOO_H_\n"
189                 "#endif // LLVM\n",
190                 "include/llvm/ADT/foo.h",
191                 StringRef("header guard does not follow preferred style")));
192 
193   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
194             "#define LLVM_ADT_FOO_H\n"
195             "#endif \\ \n"
196             "// LLVM_ADT_FOO_H\n",
197             runHeaderGuardCheckWithEndif(
198                 "#ifndef LLVM_ADT_FOO_H\n"
199                 "#define LLVM_ADT_FOO_H\n"
200                 "#endif \\ \n"
201                 "// LLVM_ADT_FOO_H\n",
202                 "include/llvm/ADT/foo.h",
203                 StringRef("backslash and newline separated by space")));
204 
205   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
206             "#define LLVM_ADT_FOO_H\n"
207             "#endif  /* LLVM_ADT_FOO_H\\ \n"
208             " FOO */",
209             runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n"
210                                          "#define LLVM_ADT_FOO_H\n"
211                                          "#endif  /* LLVM_ADT_FOO_H\\ \n"
212                                          " FOO */",
213                                          "include/llvm/ADT/foo.h", None));
214 }
215 #endif
216 
217 } // namespace test
218 } // namespace tidy
219 } // namespace clang
220