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