1 #include "ClangTidyOptions.h" 2 #include "ClangTidyTest.h" 3 #include "llvm/ADT/ArrayRef.h" 4 #include "llvm/ADT/StringRef.h" 5 #include "llvm/HeaderGuardCheck.h" 6 #include "llvm/IncludeOrderCheck.h" 7 #include "gtest/gtest.h" 8 9 using namespace clang::tidy::llvm_check; 10 11 namespace clang { 12 namespace tidy { 13 namespace test { 14 15 template <typename T> 16 static std::string runCheck(StringRef Code, const Twine &Filename, 17 Optional<StringRef> ExpectedWarning, 18 std::map<StringRef, StringRef> PathsToContent = 19 std::map<StringRef, StringRef>()) { 20 std::vector<ClangTidyError> Errors; 21 std::string Result = test::runCheckOnCode<T>( 22 Code, &Errors, Filename, std::string("-xc++-header"), ClangTidyOptions{}, 23 std::move(PathsToContent)); 24 if (Errors.size() != (size_t)ExpectedWarning.hasValue()) 25 return "invalid error count"; 26 if (ExpectedWarning && *ExpectedWarning != Errors.back().Message.Message) 27 return "expected: '" + ExpectedWarning->str() + "', saw: '" + 28 Errors.back().Message.Message + "'"; 29 return Result; 30 } 31 32 static std::string runHeaderGuardCheck(StringRef Code, const Twine &Filename, 33 Optional<StringRef> ExpectedWarning) { 34 return runCheck<LLVMHeaderGuardCheck>(Code, Filename, 35 std::move(ExpectedWarning)); 36 } 37 38 static std::string 39 runIncludeOrderCheck(StringRef Code, const Twine &Filename, 40 Optional<StringRef> ExpectedWarning, 41 llvm::ArrayRef<llvm::StringLiteral> Includes) { 42 std::map<StringRef, StringRef> PathsToContent; 43 for (auto Include : Includes) 44 PathsToContent.emplace(Include, ""); 45 return runCheck<IncludeOrderCheck>(Code, Filename, std::move(ExpectedWarning), 46 PathsToContent); 47 } 48 49 namespace { 50 struct WithEndifComment : public LLVMHeaderGuardCheck { 51 WithEndifComment(StringRef Name, ClangTidyContext *Context) 52 : LLVMHeaderGuardCheck(Name, Context) {} 53 bool shouldSuggestEndifComment(StringRef Filename) override { return true; } 54 }; 55 56 static std::string 57 runHeaderGuardCheckWithEndif(StringRef Code, const Twine &Filename, 58 Optional<StringRef> ExpectedWarning) { 59 return runCheck<WithEndifComment>(Code, Filename, std::move(ExpectedWarning)); 60 } 61 } // namespace 62 63 TEST(LLVMHeaderGuardCheckTest, FixHeaderGuards) { 64 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 65 "#define LLVM_ADT_FOO_H\n" 66 "#endif\n", 67 runHeaderGuardCheck( 68 "#ifndef FOO\n" 69 "#define FOO\n" 70 "#endif\n", 71 "include/llvm/ADT/foo.h", 72 StringRef("header guard does not follow preferred style"))); 73 74 // Allow trailing underscores. 75 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n" 76 "#define LLVM_ADT_FOO_H_\n" 77 "#endif\n", 78 runHeaderGuardCheck("#ifndef LLVM_ADT_FOO_H_\n" 79 "#define LLVM_ADT_FOO_H_\n" 80 "#endif\n", 81 "include/llvm/ADT/foo.h", None)); 82 83 EXPECT_EQ("#ifndef LLVM_CLANG_C_BAR_H\n" 84 "#define LLVM_CLANG_C_BAR_H\n" 85 "\n" 86 "\n" 87 "#endif\n", 88 runHeaderGuardCheck("", "./include/clang-c/bar.h", 89 StringRef("header is missing header guard"))); 90 91 EXPECT_EQ("#ifndef LLVM_CLANG_LIB_CODEGEN_C_H\n" 92 "#define LLVM_CLANG_LIB_CODEGEN_C_H\n" 93 "\n" 94 "\n" 95 "#endif\n", 96 runHeaderGuardCheck("", "tools/clang/lib/CodeGen/c.h", 97 StringRef("header is missing header guard"))); 98 99 EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n" 100 "#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n" 101 "\n" 102 "\n" 103 "#endif\n", 104 runHeaderGuardCheck("", "tools/clang/tools/extra/clang-tidy/x.h", 105 StringRef("header is missing header guard"))); 106 107 EXPECT_EQ( 108 "int foo;\n" 109 "#ifndef LLVM_CLANG_BAR_H\n" 110 "#define LLVM_CLANG_BAR_H\n" 111 "#endif\n", 112 runHeaderGuardCheck("int foo;\n" 113 "#ifndef LLVM_CLANG_BAR_H\n" 114 "#define LLVM_CLANG_BAR_H\n" 115 "#endif\n", 116 "include/clang/bar.h", 117 StringRef("code/includes outside of area guarded by " 118 "header guard; consider moving it"))); 119 120 EXPECT_EQ( 121 "#ifndef LLVM_CLANG_BAR_H\n" 122 "#define LLVM_CLANG_BAR_H\n" 123 "#endif\n" 124 "int foo;\n", 125 runHeaderGuardCheck("#ifndef LLVM_CLANG_BAR_H\n" 126 "#define LLVM_CLANG_BAR_H\n" 127 "#endif\n" 128 "int foo;\n", 129 "include/clang/bar.h", 130 StringRef("code/includes outside of area guarded by " 131 "header guard; consider moving it"))); 132 133 EXPECT_EQ("#ifndef LLVM_CLANG_BAR_H\n" 134 "#define LLVM_CLANG_BAR_H\n" 135 "\n" 136 "int foo;\n" 137 "#ifndef FOOLOLO\n" 138 "#define FOOLOLO\n" 139 "#endif\n" 140 "\n" 141 "#endif\n", 142 runHeaderGuardCheck("int foo;\n" 143 "#ifndef FOOLOLO\n" 144 "#define FOOLOLO\n" 145 "#endif\n", 146 "include/clang/bar.h", 147 StringRef("header is missing header guard"))); 148 149 // Fix incorrect #endif comments even if we shouldn't add new ones. 150 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 151 "#define LLVM_ADT_FOO_H\n" 152 "#endif // LLVM_ADT_FOO_H\n", 153 runHeaderGuardCheck( 154 "#ifndef FOO\n" 155 "#define FOO\n" 156 "#endif // FOO\n", 157 "include/llvm/ADT/foo.h", 158 StringRef("header guard does not follow preferred style"))); 159 160 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 161 "#define LLVM_ADT_FOO_H\n" 162 "#endif // LLVM_ADT_FOO_H\n", 163 runHeaderGuardCheckWithEndif( 164 "#ifndef FOO\n" 165 "#define FOO\n" 166 "#endif\n", 167 "include/llvm/ADT/foo.h", 168 StringRef("header guard does not follow preferred style"))); 169 170 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 171 "#define LLVM_ADT_FOO_H\n" 172 "#endif // LLVM_ADT_FOO_H\n", 173 runHeaderGuardCheckWithEndif( 174 "#ifndef LLVM_ADT_FOO_H\n" 175 "#define LLVM_ADT_FOO_H\n" 176 "#endif // LLVM_H\n", 177 "include/llvm/ADT/foo.h", 178 StringRef("#endif for a header guard should reference the " 179 "guard macro in a comment"))); 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("#ifndef LLVM_ADT_FOO_H\n" 185 "#define LLVM_ADT_FOO_H\n" 186 "#endif /* LLVM_ADT_FOO_H */\n", 187 "include/llvm/ADT/foo.h", None)); 188 189 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n" 190 "#define LLVM_ADT_FOO_H_\n" 191 "#endif // LLVM_ADT_FOO_H_\n", 192 runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H_\n" 193 "#define LLVM_ADT_FOO_H_\n" 194 "#endif // LLVM_ADT_FOO_H_\n", 195 "include/llvm/ADT/foo.h", None)); 196 197 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 198 "#define LLVM_ADT_FOO_H\n" 199 "#endif // LLVM_ADT_FOO_H\n", 200 runHeaderGuardCheckWithEndif( 201 "#ifndef LLVM_ADT_FOO_H_\n" 202 "#define LLVM_ADT_FOO_H_\n" 203 "#endif // LLVM\n", 204 "include/llvm/ADT/foo.h", 205 StringRef("header guard does not follow preferred style"))); 206 207 // An extra space inside the comment is OK. 208 llvm::StringRef WithExtraSpace = "#ifndef LLVM_ADT_FOO_H\n" 209 "#define LLVM_ADT_FOO_H\n" 210 "#endif // LLVM_ADT_FOO_H\n"; 211 EXPECT_EQ(WithExtraSpace, 212 runHeaderGuardCheckWithEndif(WithExtraSpace, 213 "include/llvm/ADT/foo.h", None)); 214 215 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 216 "#define LLVM_ADT_FOO_H\n" 217 "#endif \\ \n" 218 "// LLVM_ADT_FOO_H\n", 219 runHeaderGuardCheckWithEndif( 220 "#ifndef LLVM_ADT_FOO_H\n" 221 "#define LLVM_ADT_FOO_H\n" 222 "#endif \\ \n" 223 "// LLVM_ADT_FOO_H\n", 224 "include/llvm/ADT/foo.h", 225 StringRef("backslash and newline separated by space"))); 226 227 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 228 "#define LLVM_ADT_FOO_H\n" 229 "#endif /* LLVM_ADT_FOO_H\\ \n" 230 " FOO */", 231 runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n" 232 "#define LLVM_ADT_FOO_H\n" 233 "#endif /* LLVM_ADT_FOO_H\\ \n" 234 " FOO */", 235 "include/llvm/ADT/foo.h", None)); 236 237 EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 238 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 239 "\n" 240 "\n" 241 "#endif\n", 242 runHeaderGuardCheck( 243 "", "/llvm-project/clang-tools-extra/clangd/foo.h", 244 StringRef("header is missing header guard"))); 245 246 // Substitution of characters should not result in a header guard starting 247 // with "_". 248 EXPECT_EQ("#ifndef BAR_H\n" 249 "#define BAR_H\n" 250 "\n" 251 "\n" 252 "#endif\n", 253 runHeaderGuardCheck("", "include/--bar.h", 254 StringRef("header is missing header guard"))); 255 256 #ifdef WIN32 257 // Check interaction with Windows-style path separators (\). 258 EXPECT_EQ( 259 "#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 260 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 261 "\n" 262 "\n" 263 "#endif\n", 264 runHeaderGuardCheck("", "llvm-project\\clang-tools-extra\\clangd\\foo.h", 265 StringRef("header is missing header guard"))); 266 267 EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 268 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 269 "\n" 270 "\n" 271 "#endif\n", 272 runHeaderGuardCheck( 273 "", "C:\\llvm-project\\clang-tools-extra\\clangd\\foo.h", 274 StringRef("header is missing header guard"))); 275 276 EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 277 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 278 "\n" 279 "\n" 280 "#endif\n", 281 runHeaderGuardCheck( 282 "", 283 "\\\\SMBShare\\llvm-project\\clang-tools-extra\\clangd\\foo.h", 284 StringRef("header is missing header guard"))); 285 286 EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 287 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 288 "\n" 289 "\n" 290 "#endif\n", 291 runHeaderGuardCheck( 292 "", "\\\\?\\C:\\llvm-project\\clang-tools-extra\\clangd\\foo.h", 293 StringRef("header is missing header guard"))); 294 #endif 295 } 296 297 TEST(IncludeOrderCheck, GTestHeaders) { 298 EXPECT_EQ( 299 R"cpp( 300 #include "foo.h" 301 #include "llvm/foo.h" 302 #include "gtest/foo.h" 303 #include <algorithm>)cpp", 304 runIncludeOrderCheck( 305 R"cpp( 306 #include "foo.h" 307 #include "llvm/foo.h" 308 #include <algorithm> 309 #include "gtest/foo.h")cpp", 310 "foo.cc", StringRef("#includes are not sorted properly"), 311 {"foo.h", "algorithm", "gtest/foo.h", "llvm/foo.h"})); 312 } 313 314 } // namespace test 315 } // namespace tidy 316 } // namespace clang 317