Index: clang/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif =================================================================== --- clang/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif +++ clang/test/Analysis/diagnostics/Inputs/expected-sarif/sarif-multi-diagnostic-test.c.sarif @@ -451,7 +451,7 @@ "fullDescription": { "text": "Check for logical errors for function calls and Objective-C message expressions (e.g., uninitialized arguments, null function pointers)" }, - "helpUri": "https://clang-analyzer.llvm.org/available_checks.html#core.CallAndMessage", + "helpUri": "https://clang.llvm.org/docs/analyzer/checkers.html#core-callandmessage", "id": "core.CallAndMessage", "name": "core.CallAndMessage" }, @@ -459,7 +459,7 @@ "fullDescription": { "text": "Check for division by zero" }, - "helpUri": "https://clang-analyzer.llvm.org/available_checks.html#core.DivideZero", + "helpUri": "https://clang.llvm.org/docs/analyzer/checkers.html#core-dividezero", "id": "core.DivideZero", "name": "core.DivideZero" }, @@ -467,7 +467,7 @@ "fullDescription": { "text": "Check for memory leaks, double free, and use-after-free problems. Traces memory managed by malloc()/free()." }, - "helpUri": "https://clang-analyzer.llvm.org/available_checks.html#unix.Malloc", + "helpUri": "https://clang.llvm.org/docs/analyzer/checkers.html#unix-malloc", "id": "unix.Malloc", "name": "unix.Malloc" } Index: clang/utils/TableGen/ClangSACheckersEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangSACheckersEmitter.cpp +++ clang/utils/TableGen/ClangSACheckersEmitter.cpp @@ -24,37 +24,39 @@ // Static Analyzer Checkers Tables generation //===----------------------------------------------------------------------===// -static std::string getPackageFullName(const Record *R); +static std::string getPackageFullName(const Record *R, StringRef Sep = "."); -static std::string getParentPackageFullName(const Record *R) { - std::string name; +static std::string getParentPackageFullName(const Record *R, + StringRef Sep = ".") { if (DefInit *DI = dyn_cast(R->getValueInit("ParentPackage"))) - name = getPackageFullName(DI->getDef()); - return name; + return getPackageFullName(DI->getDef(), Sep); + return ""; } -static std::string getPackageFullName(const Record *R) { - std::string name = getParentPackageFullName(R); - if (!name.empty()) - name += "."; - assert(!R->getValueAsString("PackageName").empty()); - name += R->getValueAsString("PackageName"); - return name; +static std::string getPackageFullName(const Record *R, StringRef Sep) { + std::string ParentPkgName = getParentPackageFullName(R, Sep); + StringRef PackageName = R->getValueAsString("PackageName"); + assert(!PackageName.empty()); + + if (ParentPkgName.empty()) + return PackageName.str(); + return (Twine{ParentPkgName} + Sep + PackageName).str(); } -static std::string getCheckerFullName(const Record *R) { - std::string name = getParentPackageFullName(R); - if (!name.empty()) - name += "."; - assert(!R->getValueAsString("CheckerName").empty()); - name += R->getValueAsString("CheckerName"); - return name; +static std::string getCheckerFullName(const Record *R, StringRef Sep = ".") { + std::string ParentPkgName = getParentPackageFullName(R, Sep); + StringRef CheckerName = R->getValueAsString("CheckerName"); + assert(!CheckerName.empty()); + + if (ParentPkgName.empty()) + return CheckerName.str(); + return (Twine{ParentPkgName} + Sep + CheckerName).str(); } static std::string getStringValue(const Record &R, StringRef field) { if (StringInit *SI = dyn_cast(R.getValueInit(field))) return std::string(SI->getValue()); - return std::string(); + return ""; } // Calculates the integer value representing the BitsInit object @@ -74,20 +76,19 @@ } static std::string getCheckerDocs(const Record &R) { - StringRef LandingPage; - if (BitsInit *BI = R.getValueAsBitsInit("Documentation")) { - uint64_t V = getValueFromBitsInit(BI, R); - if (V == 1) - LandingPage = "available_checks.html"; - else if (V == 2) - LandingPage = "alpha_checks.html"; - } - - if (LandingPage.empty()) + const BitsInit *BI = R.getValueAsBitsInit("Documentation"); + if (!BI) + PrintFatalError(R.getLoc(), + "missing Documentation for " + getCheckerFullName(&R)); + + // Ignore 'Documentation' checkers. + if (getValueFromBitsInit(BI, R) == 0) return ""; - return (llvm::Twine("https://clang-analyzer.llvm.org/") + LandingPage + "#" + - getCheckerFullName(&R)) + std::string CheckerFullName = StringRef(getCheckerFullName(&R, "-")).lower(); + + return (llvm::Twine("https://clang.llvm.org/docs/analyzer/checkers.html#") + + CheckerFullName) .str(); }