Fix llvm-header-guard check.

Summary:
This patch makes the check work better for LLVM code:
  * always fix existing #endif comments
  * use one space before the comment (+allow customization for other styles)

Reviewers: djasper

Reviewed By: djasper

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D5795

llvm-svn: 219789
This commit is contained in:
Alexander Kornienko 2014-10-15 12:18:35 +00:00
parent bebe0c6918
commit 81d4f939bc
3 changed files with 31 additions and 10 deletions

View File

@ -150,15 +150,15 @@ public:
bool wouldFixEndifComment(StringRef FileName, SourceLocation EndIf, bool wouldFixEndifComment(StringRef FileName, SourceLocation EndIf,
StringRef HeaderGuard, StringRef HeaderGuard,
size_t *EndIfLenPtr = nullptr) { size_t *EndIfLenPtr = nullptr) {
if (!Check->shouldSuggestEndifComment(FileName)) if (!EndIf.isValid())
return false; return false;
const char *EndIfData = PP->getSourceManager().getCharacterData(EndIf); const char *EndIfData = PP->getSourceManager().getCharacterData(EndIf);
size_t EndIfLen = std::strcspn(EndIfData, "\r\n"); size_t EndIfLen = std::strcspn(EndIfData, "\r\n");
if (EndIfLenPtr) if (EndIfLenPtr)
*EndIfLenPtr = EndIfLen; *EndIfLenPtr = EndIfLen;
StringRef EndIfStr(EndIfData, EndIfLen); StringRef EndIfStr(EndIfData, EndIfLen);
EndIfStr = EndIfStr.substr(EndIfStr.find_first_not_of("#endif \t"));
// Give up if there's an escaped newline. // Give up if there's an escaped newline.
size_t FindEscapedNewline = EndIfStr.find_last_not_of(' '); size_t FindEscapedNewline = EndIfStr.find_last_not_of(' ');
@ -166,8 +166,13 @@ public:
EndIfStr[FindEscapedNewline] == '\\') EndIfStr[FindEscapedNewline] == '\\')
return false; return false;
return (EndIf.isValid() && !EndIfStr.endswith("// " + HeaderGuard.str()) && if (!Check->shouldSuggestEndifComment(FileName) &&
!EndIfStr.endswith("/* " + HeaderGuard.str() + " */")); !(EndIfStr.startswith("//") ||
(EndIfStr.startswith("/*") && EndIfStr.endswith("*/"))))
return false;
return (EndIfStr != "// " + HeaderGuard.str()) &&
(EndIfStr != "/* " + HeaderGuard.str() + " */");
} }
/// \brief Look for header guards that don't match the preferred style. Emit /// \brief Look for header guards that don't match the preferred style. Emit
@ -207,11 +212,10 @@ public:
std::vector<FixItHint> &FixIts) { std::vector<FixItHint> &FixIts) {
size_t EndIfLen; size_t EndIfLen;
if (wouldFixEndifComment(FileName, EndIf, HeaderGuard, &EndIfLen)) { if (wouldFixEndifComment(FileName, EndIf, HeaderGuard, &EndIfLen)) {
std::string Correct = "endif // " + HeaderGuard.str();
FixIts.push_back(FixItHint::CreateReplacement( FixIts.push_back(FixItHint::CreateReplacement(
CharSourceRange::getCharRange(EndIf, CharSourceRange::getCharRange(EndIf,
EndIf.getLocWithOffset(EndIfLen)), EndIf.getLocWithOffset(EndIfLen)),
Correct)); Check->formatEndIf(HeaderGuard)));
} }
} }
@ -261,7 +265,7 @@ public:
<< FixItHint::CreateInsertion( << FixItHint::CreateInsertion(
SM.getLocForEndOfFile(FID), SM.getLocForEndOfFile(FID),
Check->shouldSuggestEndifComment(FileName) Check->shouldSuggestEndifComment(FileName)
? "\n#endif // " + CPPVar + "\n" ? "\n#" + Check->formatEndIf(CPPVar) + "\n"
: "\n#endif\n"); : "\n#endif\n");
} }
} }
@ -294,5 +298,9 @@ bool HeaderGuardCheck::shouldSuggestToAddHeaderGuard(StringRef FileName) {
return FileName.endswith(".h"); return FileName.endswith(".h");
} }
std::string HeaderGuardCheck::formatEndIf(StringRef HeaderGuard) {
return "endif // " + HeaderGuard.str();
}
} // namespace tidy } // namespace tidy
} // namespace clang } // namespace clang

View File

@ -32,6 +32,9 @@ public:
/// \brief Returns true if the checker should add a header guard to the file /// \brief Returns true if the checker should add a header guard to the file
/// if it has none. /// if it has none.
virtual bool shouldSuggestToAddHeaderGuard(StringRef Filename); virtual bool shouldSuggestToAddHeaderGuard(StringRef Filename);
/// \brief Returns a replacement for endif line with a comment mentioning
/// \p HeaderGuard. The replacement should start with "endif".
virtual std::string formatEndIf(StringRef HeaderGuard);
/// \brief Get the canonical header guard for a file. /// \brief Get the canonical header guard for a file.
virtual std::string getHeaderGuard(StringRef Filename, virtual std::string getHeaderGuard(StringRef Filename,
StringRef OldGuard = StringRef()) = 0; StringRef OldGuard = StringRef()) = 0;

View File

@ -103,6 +103,16 @@ TEST(LLVMHeaderGuardCheckTest, FixHeaderGuards) {
"#endif\n", "#endif\n",
"include/clang/bar.h", /*ExpectedWarnings=*/1)); "include/clang/bar.h", /*ExpectedWarnings=*/1));
// Fix incorrect #endif comments even if we shouldn't add new ones.
EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
"#define LLVM_ADT_FOO_H\n"
"#endif // LLVM_ADT_FOO_H\n",
runHeaderGuardCheck("#ifndef FOO\n"
"#define FOO\n"
"#endif // FOO\n",
"include/llvm/ADT/foo.h",
/*ExpectedWarnings=*/1));
EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n" EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"
"#define LLVM_ADT_FOO_H\n" "#define LLVM_ADT_FOO_H\n"
"#endif // LLVM_ADT_FOO_H\n", "#endif // LLVM_ADT_FOO_H\n",