diff --git a/clang/include/clang/Analysis/IssueHash.h b/clang/include/clang/Analysis/IssueHash.h new file mode 100644 --- /dev/null +++ b/clang/include/clang/Analysis/IssueHash.h @@ -0,0 +1,49 @@ +//===---------- IssueHash.h - Generate identification hashes ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H +#define LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H + +#include "llvm/ADT/SmallString.h" + +namespace clang { +class Decl; +class FullSourceLoc; +class LangOptions; + +/// Returns an opaque identifier for a diagnostic. +/// +/// This opaque identifier is intended to be stable even when the source code +/// is changed. It allows to track diagnostics in the long term, for example, +/// find which diagnostics are "new", maintain a database of suppressed +/// diagnostics etc. +/// +/// We may introduce more variants of issue hashes in the future +/// but older variants will still be available for compatibility. +/// +/// This hash is based on the following information: +/// - Name of the checker that emitted the diagnostic. +/// - Warning message. +/// - Name of the enclosing declaration. +/// - Contents of the line of code with the issue, excluding whitespace. +/// - Column number (but not the line number! - which makes it stable). +llvm::SmallString<32> getIssueHash(const FullSourceLoc &IssueLoc, + llvm::StringRef CheckerName, + llvm::StringRef WarningMessage, + const Decl *IssueDecl, + const LangOptions &LangOpts); + +/// Get the unhashed string representation of the V1 issue hash. +/// When hashed, it becomes the actual issue hash. Useful for testing. +/// See GetIssueHashV1() for more information. +std::string getIssueString(const FullSourceLoc &IssueLoc, + llvm::StringRef CheckerName, + llvm::StringRef WarningMessage, + const Decl *IssueDecl, const LangOptions &LangOpts); +} // namespace clang + +#endif diff --git a/clang/include/clang/StaticAnalyzer/Core/IssueHash.h b/clang/include/clang/StaticAnalyzer/Core/IssueHash.h deleted file mode 100644 --- a/clang/include/clang/StaticAnalyzer/Core/IssueHash.h +++ /dev/null @@ -1,50 +0,0 @@ -//===---------- IssueHash.h - Generate identification hashes ----*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H -#define LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H - -#include "llvm/ADT/SmallString.h" - -namespace clang { -class Decl; -class SourceManager; -class FullSourceLoc; -class LangOptions; - -/// Get an MD5 hash to help identify bugs. -/// -/// This function returns a hash that helps identify bugs within a source file. -/// This identification can be utilized to diff diagnostic results on different -/// snapshots of a projects, or maintain a database of suppressed diagnotics. -/// -/// The hash contains the normalized text of the location associated with the -/// diagnostic. Normalization means removing the whitespaces. The associated -/// location is the either the last location of a diagnostic path or a uniqueing -/// location. The bugtype and the name of the checker is also part of the hash. -/// The last component is the string representation of the enclosing declaration -/// of the associated location. -/// -/// In case a new hash is introduced, the old one should still be maintained for -/// a while. One should not introduce a new hash for every change, it is -/// possible to introduce experimental hashes that may change in the future. -/// Such hashes should be marked as experimental using a comment in the plist -/// files. -llvm::SmallString<32> GetIssueHash(const SourceManager &SM, - FullSourceLoc &IssueLoc, - llvm::StringRef CheckerName, - llvm::StringRef BugType, const Decl *D, - const LangOptions &LangOpts); - -/// Get the string representation of issue hash. See GetIssueHash() for -/// more information. -std::string GetIssueString(const SourceManager &SM, FullSourceLoc &IssueLoc, - llvm::StringRef CheckerName, llvm::StringRef BugType, - const Decl *D, const LangOptions &LangOpts); -} // namespace clang - -#endif diff --git a/clang/lib/Analysis/CMakeLists.txt b/clang/lib/Analysis/CMakeLists.txt --- a/clang/lib/Analysis/CMakeLists.txt +++ b/clang/lib/Analysis/CMakeLists.txt @@ -17,6 +17,7 @@ CodeInjector.cpp Dominators.cpp ExprMutationAnalyzer.cpp + IssueHash.cpp LiveVariables.cpp ObjCNoReturn.cpp PathDiagnostic.cpp diff --git a/clang/lib/StaticAnalyzer/Core/IssueHash.cpp b/clang/lib/Analysis/IssueHash.cpp rename from clang/lib/StaticAnalyzer/Core/IssueHash.cpp rename to clang/lib/Analysis/IssueHash.cpp --- a/clang/lib/StaticAnalyzer/Core/IssueHash.cpp +++ b/clang/lib/Analysis/IssueHash.cpp @@ -5,7 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Core/IssueHash.h" + +#include "clang/Analysis/IssueHash.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -131,7 +132,7 @@ return *LI; } -static std::string NormalizeLine(const SourceManager &SM, FullSourceLoc &L, +static std::string NormalizeLine(const SourceManager &SM, const FullSourceLoc &L, const LangOptions &LangOpts) { static StringRef Whitespaces = " \t\n"; @@ -167,7 +168,7 @@ return LineBuff.str(); } -static llvm::SmallString<32> GetHashOfContent(StringRef Content) { +static llvm::SmallString<32> GetMD5HashOfContent(StringRef Content) { llvm::MD5 Hash; llvm::MD5::MD5Result MD5Res; SmallString<32> Res; @@ -179,26 +180,27 @@ return Res; } -std::string clang::GetIssueString(const SourceManager &SM, - FullSourceLoc &IssueLoc, - StringRef CheckerName, StringRef BugType, - const Decl *D, +std::string clang::getIssueString(const FullSourceLoc &IssueLoc, + StringRef CheckerName, + StringRef WarningMessage, + const Decl *IssueDecl, const LangOptions &LangOpts) { static StringRef Delimiter = "$"; return (llvm::Twine(CheckerName) + Delimiter + - GetEnclosingDeclContextSignature(D) + Delimiter + + GetEnclosingDeclContextSignature(IssueDecl) + Delimiter + Twine(IssueLoc.getExpansionColumnNumber()) + Delimiter + - NormalizeLine(SM, IssueLoc, LangOpts) + Delimiter + BugType) + NormalizeLine(IssueLoc.getManager(), IssueLoc, LangOpts) + + Delimiter + WarningMessage) .str(); } -SmallString<32> clang::GetIssueHash(const SourceManager &SM, - FullSourceLoc &IssueLoc, - StringRef CheckerName, StringRef BugType, - const Decl *D, +SmallString<32> clang::getIssueHash(const FullSourceLoc &IssueLoc, + StringRef CheckerName, + StringRef WarningMessage, + const Decl *IssueDecl, const LangOptions &LangOpts) { - return GetHashOfContent( - GetIssueString(SM, IssueLoc, CheckerName, BugType, D, LangOpts)); + return GetMD5HashOfContent(getIssueString( + IssueLoc, CheckerName, WarningMessage, IssueDecl, LangOpts)); } diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "Taint.h" +#include "clang/Analysis/IssueHash.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Checkers/SValExplainer.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" -#include "clang/StaticAnalyzer/Core/IssueHash.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h" @@ -326,7 +326,7 @@ const SourceManager &SM = C.getSourceManager(); FullSourceLoc FL(CE->getArg(0)->getBeginLoc(), SM); std::string HashContent = - GetIssueString(SM, FL, getCheckerName().getName(), "Category", + getIssueString(FL, getCheckerName().getName(), "Category", C.getLocationContext()->getDecl(), Opts); reportBug(HashContent, C); diff --git a/clang/lib/StaticAnalyzer/Core/CMakeLists.txt b/clang/lib/StaticAnalyzer/Core/CMakeLists.txt --- a/clang/lib/StaticAnalyzer/Core/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Core/CMakeLists.txt @@ -31,7 +31,6 @@ ExprEngineObjC.cpp FunctionSummary.cpp HTMLDiagnostics.cpp - IssueHash.cpp LoopUnrolling.cpp LoopWidening.cpp MemRegion.cpp diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Analysis/IssueHash.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" @@ -23,7 +24,6 @@ #include "clang/Lex/Token.h" #include "clang/Rewrite/Core/HTMLRewrite.h" #include "clang/Rewrite/Core/Rewriter.h" -#include "clang/StaticAnalyzer/Core/IssueHash.h" #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" @@ -583,8 +583,8 @@ os << "\n\n"; os << "\n\n"; os << "\n