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 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 208 "#define LLVM_ADT_FOO_H\n" 209 "#endif \\ \n" 210 "// LLVM_ADT_FOO_H\n", 211 runHeaderGuardCheckWithEndif( 212 "#ifndef LLVM_ADT_FOO_H\n" 213 "#define LLVM_ADT_FOO_H\n" 214 "#endif \\ \n" 215 "// LLVM_ADT_FOO_H\n", 216 "include/llvm/ADT/foo.h", 217 StringRef("backslash and newline separated by space"))); 218 219 EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" 220 "#define LLVM_ADT_FOO_H\n" 221 "#endif /* LLVM_ADT_FOO_H\\ \n" 222 " FOO */", 223 runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n" 224 "#define LLVM_ADT_FOO_H\n" 225 "#endif /* LLVM_ADT_FOO_H\\ \n" 226 " FOO */", 227 "include/llvm/ADT/foo.h", None)); 228 229 EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 230 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 231 "\n" 232 "\n" 233 "#endif\n", 234 runHeaderGuardCheck( 235 "", "/llvm-project/clang-tools-extra/clangd/foo.h", 236 StringRef("header is missing header guard"))); 237 238 // Substitution of characters should not result in a header guard starting 239 // with "_". 240 EXPECT_EQ("#ifndef BAR_H\n" 241 "#define BAR_H\n" 242 "\n" 243 "\n" 244 "#endif\n", 245 runHeaderGuardCheck("", "include/--bar.h", 246 StringRef("header is missing header guard"))); 247 248 #ifdef WIN32 249 // Check interaction with Windows-style path separators (\). 250 EXPECT_EQ( 251 "#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 252 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 253 "\n" 254 "\n" 255 "#endif\n", 256 runHeaderGuardCheck("", "llvm-project\\clang-tools-extra\\clangd\\foo.h", 257 StringRef("header is missing header guard"))); 258 259 EXPECT_EQ("#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( 265 "", "C:\\llvm-project\\clang-tools-extra\\clangd\\foo.h", 266 StringRef("header is missing header guard"))); 267 268 EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 269 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 270 "\n" 271 "\n" 272 "#endif\n", 273 runHeaderGuardCheck( 274 "", 275 "\\\\SMBShare\\llvm-project\\clang-tools-extra\\clangd\\foo.h", 276 StringRef("header is missing header guard"))); 277 278 EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 279 "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n" 280 "\n" 281 "\n" 282 "#endif\n", 283 runHeaderGuardCheck( 284 "", "\\\\?\\C:\\llvm-project\\clang-tools-extra\\clangd\\foo.h", 285 StringRef("header is missing header guard"))); 286 #endif 287 } 288 289 TEST(IncludeOrderCheck, GTestHeaders) { 290 EXPECT_EQ( 291 R"cpp( 292 #include "foo.h" 293 #include "llvm/foo.h" 294 #include "gtest/foo.h" 295 #include <algorithm>)cpp", 296 runIncludeOrderCheck( 297 R"cpp( 298 #include "foo.h" 299 #include "llvm/foo.h" 300 #include <algorithm> 301 #include "gtest/foo.h")cpp", 302 "foo.cc", StringRef("#includes are not sorted properly"), 303 {"foo.h", "algorithm", "gtest/foo.h", "llvm/foo.h"})); 304 } 305 306 } // namespace test 307 } // namespace tidy 308 } // namespace clang 309