xref: /llvm-project/clang-tools-extra/unittests/clang-tidy/LLVMModuleTest.cpp (revision b4f6f1c9369ec4bb1c10852283a8c7e8c39e1a8d)
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 static std::string runHeaderGuardCheck(StringRef Code, const Twine &Filename,
13                                        Optional<StringRef> ExpectedWarning) {
14   std::vector<ClangTidyError> Errors;
15   std::string Result = test::runCheckOnCode<LLVMHeaderGuardCheck>(
16       Code, &Errors, Filename, std::string("-xc++-header"));
17   if (Errors.size() != (size_t)ExpectedWarning.hasValue())
18     return "invalid error count";
19   if (ExpectedWarning && *ExpectedWarning != Errors.back().Message.Message)
20     return "expected: '" + ExpectedWarning->str() + "', saw: '" +
21            Errors.back().Message.Message + "'";
22   return Result;
23 }
24 
25 namespace {
26 struct WithEndifComment : public LLVMHeaderGuardCheck {
27   WithEndifComment(StringRef Name, ClangTidyContext *Context)
28       : LLVMHeaderGuardCheck(Name, Context) {}
29   bool shouldSuggestEndifComment(StringRef Filename) override { return true; }
30 };
31 } // namespace
32 
33 static std::string
34 runHeaderGuardCheckWithEndif(StringRef Code, const Twine &Filename,
35                              Optional<StringRef> ExpectedWarning) {
36   std::vector<ClangTidyError> Errors;
37   std::string Result = test::runCheckOnCode<WithEndifComment>(
38       Code, &Errors, Filename, std::string("-xc++-header"));
39   if (Errors.size() != (size_t)ExpectedWarning.hasValue())
40     return "invalid error count";
41   if (ExpectedWarning && *ExpectedWarning != Errors.back().Message.Message)
42     return "expected: '" + ExpectedWarning->str() + "', saw: '" +
43            Errors.back().Message.Message + "'";
44   return Result;
45 }
46 
47 TEST(LLVMHeaderGuardCheckTest, FixHeaderGuards) {
48   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
49             "#define LLVM_ADT_FOO_H\n"
50             "#endif\n",
51             runHeaderGuardCheck(
52                 "#ifndef FOO\n"
53                 "#define FOO\n"
54                 "#endif\n",
55                 "include/llvm/ADT/foo.h",
56                 StringRef("header guard does not follow preferred style")));
57 
58   // Allow trailing underscores.
59   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n"
60             "#define LLVM_ADT_FOO_H_\n"
61             "#endif\n",
62             runHeaderGuardCheck("#ifndef LLVM_ADT_FOO_H_\n"
63                                 "#define LLVM_ADT_FOO_H_\n"
64                                 "#endif\n",
65                                 "include/llvm/ADT/foo.h", None));
66 
67   EXPECT_EQ("#ifndef LLVM_CLANG_C_BAR_H\n"
68             "#define LLVM_CLANG_C_BAR_H\n"
69             "\n"
70             "\n"
71             "#endif\n",
72             runHeaderGuardCheck("", "./include/clang-c/bar.h",
73                                 StringRef("header is missing header guard")));
74 
75   EXPECT_EQ("#ifndef LLVM_CLANG_LIB_CODEGEN_C_H\n"
76             "#define LLVM_CLANG_LIB_CODEGEN_C_H\n"
77             "\n"
78             "\n"
79             "#endif\n",
80             runHeaderGuardCheck("", "tools/clang/lib/CodeGen/c.h",
81                                 StringRef("header is missing header guard")));
82 
83   EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n"
84             "#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n"
85             "\n"
86             "\n"
87             "#endif\n",
88             runHeaderGuardCheck("", "tools/clang/tools/extra/clang-tidy/x.h",
89                                 StringRef("header is missing header guard")));
90 
91   EXPECT_EQ(
92       "int foo;\n"
93       "#ifndef LLVM_CLANG_BAR_H\n"
94       "#define LLVM_CLANG_BAR_H\n"
95       "#endif\n",
96       runHeaderGuardCheck("int foo;\n"
97                           "#ifndef LLVM_CLANG_BAR_H\n"
98                           "#define LLVM_CLANG_BAR_H\n"
99                           "#endif\n",
100                           "include/clang/bar.h",
101                           StringRef("code/includes outside of area guarded by "
102                                     "header guard; consider moving it")));
103 
104   EXPECT_EQ(
105       "#ifndef LLVM_CLANG_BAR_H\n"
106       "#define LLVM_CLANG_BAR_H\n"
107       "#endif\n"
108       "int foo;\n",
109       runHeaderGuardCheck("#ifndef LLVM_CLANG_BAR_H\n"
110                           "#define LLVM_CLANG_BAR_H\n"
111                           "#endif\n"
112                           "int foo;\n",
113                           "include/clang/bar.h",
114                           StringRef("code/includes outside of area guarded by "
115                                     "header guard; consider moving it")));
116 
117   EXPECT_EQ("#ifndef LLVM_CLANG_BAR_H\n"
118             "#define LLVM_CLANG_BAR_H\n"
119             "\n"
120             "int foo;\n"
121             "#ifndef FOOLOLO\n"
122             "#define FOOLOLO\n"
123             "#endif\n"
124             "\n"
125             "#endif\n",
126             runHeaderGuardCheck("int foo;\n"
127                                 "#ifndef FOOLOLO\n"
128                                 "#define FOOLOLO\n"
129                                 "#endif\n",
130                                 "include/clang/bar.h",
131                                 StringRef("header is missing header guard")));
132 
133   // Fix incorrect #endif comments even if we shouldn't add new ones.
134   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
135             "#define LLVM_ADT_FOO_H\n"
136             "#endif // LLVM_ADT_FOO_H\n",
137             runHeaderGuardCheck(
138                 "#ifndef FOO\n"
139                 "#define FOO\n"
140                 "#endif // FOO\n",
141                 "include/llvm/ADT/foo.h",
142                 StringRef("header guard does not follow preferred style")));
143 
144   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
145             "#define LLVM_ADT_FOO_H\n"
146             "#endif // LLVM_ADT_FOO_H\n",
147             runHeaderGuardCheckWithEndif(
148                 "#ifndef FOO\n"
149                 "#define FOO\n"
150                 "#endif\n",
151                 "include/llvm/ADT/foo.h",
152                 StringRef("header guard does not follow preferred style")));
153 
154   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
155             "#define LLVM_ADT_FOO_H\n"
156             "#endif // LLVM_ADT_FOO_H\n",
157             runHeaderGuardCheckWithEndif(
158                 "#ifndef LLVM_ADT_FOO_H\n"
159                 "#define LLVM_ADT_FOO_H\n"
160                 "#endif // LLVM_H\n",
161                 "include/llvm/ADT/foo.h",
162                 StringRef("#endif for a header guard should reference the "
163                           "guard macro in a comment")));
164 
165   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
166             "#define LLVM_ADT_FOO_H\n"
167             "#endif /* LLVM_ADT_FOO_H */\n",
168             runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n"
169                                          "#define LLVM_ADT_FOO_H\n"
170                                          "#endif /* LLVM_ADT_FOO_H */\n",
171                                          "include/llvm/ADT/foo.h", None));
172 
173   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n"
174             "#define LLVM_ADT_FOO_H_\n"
175             "#endif // LLVM_ADT_FOO_H_\n",
176             runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H_\n"
177                                          "#define LLVM_ADT_FOO_H_\n"
178                                          "#endif // LLVM_ADT_FOO_H_\n",
179                                          "include/llvm/ADT/foo.h", None));
180 
181   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
182             "#define LLVM_ADT_FOO_H\n"
183             "#endif // LLVM_ADT_FOO_H\n",
184             runHeaderGuardCheckWithEndif(
185                 "#ifndef LLVM_ADT_FOO_H_\n"
186                 "#define LLVM_ADT_FOO_H_\n"
187                 "#endif // LLVM\n",
188                 "include/llvm/ADT/foo.h",
189                 StringRef("header guard does not follow preferred style")));
190 
191   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
192             "#define LLVM_ADT_FOO_H\n"
193             "#endif \\ \n"
194             "// LLVM_ADT_FOO_H\n",
195             runHeaderGuardCheckWithEndif(
196                 "#ifndef LLVM_ADT_FOO_H\n"
197                 "#define LLVM_ADT_FOO_H\n"
198                 "#endif \\ \n"
199                 "// LLVM_ADT_FOO_H\n",
200                 "include/llvm/ADT/foo.h",
201                 StringRef("backslash and newline separated by space")));
202 
203   EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
204             "#define LLVM_ADT_FOO_H\n"
205             "#endif  /* LLVM_ADT_FOO_H\\ \n"
206             " FOO */",
207             runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n"
208                                          "#define LLVM_ADT_FOO_H\n"
209                                          "#endif  /* LLVM_ADT_FOO_H\\ \n"
210                                          " FOO */",
211                                          "include/llvm/ADT/foo.h", None));
212 
213   EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
214             "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
215             "\n"
216             "\n"
217             "#endif\n",
218             runHeaderGuardCheck(
219                 "", "/llvm-project/clang-tools-extra/clangd/foo.h",
220                 StringRef("header is missing header guard")));
221 
222 #ifdef WIN32
223   // Check interaction with Windows-style path separators (\).
224   EXPECT_EQ(
225       "#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
226       "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
227       "\n"
228       "\n"
229       "#endif\n",
230       runHeaderGuardCheck("", "llvm-project\\clang-tools-extra\\clangd\\foo.h",
231                           StringRef("header is missing header guard")));
232 
233   EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
234             "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
235             "\n"
236             "\n"
237             "#endif\n",
238             runHeaderGuardCheck(
239                 "", "C:\\llvm-project\\clang-tools-extra\\clangd\\foo.h",
240                 StringRef("header is missing header guard")));
241 
242   EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
243             "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
244             "\n"
245             "\n"
246             "#endif\n",
247             runHeaderGuardCheck(
248                 "",
249                 "\\\\SMBShare\\llvm-project\\clang-tools-extra\\clangd\\foo.h",
250                 StringRef("header is missing header guard")));
251 
252   EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
253             "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"
254             "\n"
255             "\n"
256             "#endif\n",
257             runHeaderGuardCheck(
258                 "", "\\\\?\\C:\\llvm-project\\clang-tools-extra\\clangd\\foo.h",
259                 StringRef("header is missing header guard")));
260 #endif
261 }
262 
263 } // namespace test
264 } // namespace tidy
265 } // namespace clang
266