[clang] 8a5cfdf - [analyzer][NFC] Remove useless class BuiltinBug

Donát Nagy via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 28 06:25:58 PDT 2023


Author: Donát Nagy
Date: 2023-08-28T15:20:14+02:00
New Revision: 8a5cfdf7851dcdb4e16c510b133d7d0e79e43fc4

URL: https://github.com/llvm/llvm-project/commit/8a5cfdf7851dcdb4e16c510b133d7d0e79e43fc4
DIFF: https://github.com/llvm/llvm-project/commit/8a5cfdf7851dcdb4e16c510b133d7d0e79e43fc4.diff

LOG: [analyzer][NFC] Remove useless class BuiltinBug

...because it provides no useful functionality compared to its base
class `BugType`.

A long time ago there were substantial differences between `BugType` and
`BuiltinBug`, but they were eliminated by commit 1bd58233 in 2009 (!).
Since then the only functionality provided by `BuiltinBug` was that it
specified `categories::LogicError` as the bug category and it stored an
extra data member `desc`.

This commit sets `categories::LogicError` as the default value of the
third argument (bug category) in the constructors of BugType and
replaces use of the `desc` field with simpler logic.

Note that `BugType` has a data member `Description` and a non-virtual
method `BugType::getDescription()` which queries it; these are distinct
from the member `desc` of `BuiltinBug` and the identically named method
`BuiltinBug::getDescription()` which queries it. This confusing name
collision was a major motivation for the elimination of `BuiltinBug`.

As this commit touches many files, I avoided functional changes and left
behind FIXME notes to mark minor issues that should be fixed later.

Differential Revision: https://reviews.llvm.org/D158855

Added: 
    

Modified: 
    clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
    clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
    clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
    clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
    clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
    clang/lib/StaticAnalyzer/Core/BugReporter.cpp
    clang/unittests/StaticAnalyzer/CallEventTest.cpp
    clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
    clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 5588811763273b..e50afd6d0da7e5 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -35,13 +35,13 @@ class BugType {
   virtual void anchor();
 
 public:
-  BugType(CheckerNameRef CheckerName, StringRef Name, StringRef Cat,
-          bool SuppressOnSink = false)
-      : CheckerName(CheckerName), Description(Name), Category(Cat),
+  BugType(CheckerNameRef CheckerName, StringRef Desc,
+          StringRef Cat = categories::LogicError, bool SuppressOnSink = false)
+      : CheckerName(CheckerName), Description(Desc), Category(Cat),
         Checker(nullptr), SuppressOnSink(SuppressOnSink) {}
-  BugType(const CheckerBase *Checker, StringRef Name, StringRef Cat,
-          bool SuppressOnSink = false)
-      : CheckerName(Checker->getCheckerName()), Description(Name),
+  BugType(const CheckerBase *Checker, StringRef Desc,
+          StringRef Cat = categories::LogicError, bool SuppressOnSink = false)
+      : CheckerName(Checker->getCheckerName()), Description(Desc),
         Category(Cat), Checker(Checker), SuppressOnSink(SuppressOnSink) {}
   virtual ~BugType() = default;
 
@@ -64,27 +64,6 @@ class BugType {
   bool isSuppressOnSink() const { return SuppressOnSink; }
 };
 
-class BuiltinBug : public BugType {
-  const std::string desc;
-  void anchor() override;
-public:
-  BuiltinBug(class CheckerNameRef checker, const char *name,
-             const char *description)
-      : BugType(checker, name, categories::LogicError), desc(description) {}
-
-  BuiltinBug(const CheckerBase *checker, const char *name,
-             const char *description)
-      : BugType(checker, name, categories::LogicError), desc(description) {}
-
-  BuiltinBug(class CheckerNameRef checker, const char *name)
-      : BugType(checker, name, categories::LogicError), desc(name) {}
-
-  BuiltinBug(const CheckerBase *checker, const char *name)
-      : BugType(checker, name, categories::LogicError), desc(name) {}
-
-  StringRef getDescription() const { return desc; }
-};
-
 } // namespace ento
 
 } // end clang namespace

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
index 03e85b9c43739a..ce126541265551 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
@@ -25,7 +25,7 @@ using namespace ento;
 namespace {
 class ArrayBoundChecker :
     public Checker<check::Location> {
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
 
 public:
   void checkLocation(SVal l, bool isLoad, const Stmt* S,
@@ -66,17 +66,15 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS,
       return;
 
     if (!BT)
-      BT.reset(new BuiltinBug(
-          this, "Out-of-bound array access",
-          "Access out-of-bound array element (buffer overflow)"));
+      BT.reset(new BugType(this, "Out-of-bound array access"));
 
     // FIXME: It would be nice to eventually make this diagnostic more clear,
     // e.g., by referencing the original declaration or by saying *why* this
     // reference is outside the range.
 
     // Generate a report for this bug.
-    auto report =
-        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
+    auto report = std::make_unique<PathSensitiveBugReport>(
+        *BT, "Access out-of-bound array element (buffer overflow)", N);
 
     report->addRange(LoadS->getSourceRange());
     C.emitReport(std::move(report));

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index 93da34ed5da4c5..db4a2fcea9b2cd 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -32,7 +32,7 @@ using namespace taint;
 namespace {
 class ArrayBoundCheckerV2 :
     public Checker<check::Location> {
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
   mutable std::unique_ptr<BugType> TaintBT;
 
   enum OOB_Kind { OOB_Precedes, OOB_Excedes };
@@ -258,7 +258,7 @@ void ArrayBoundCheckerV2::reportOOB(CheckerContext &checkerContext,
     return;
 
   if (!BT)
-    BT.reset(new BuiltinBug(this, "Out-of-bound access"));
+    BT.reset(new BugType(this, "Out-of-bound access"));
 
   // FIXME: This diagnostics are preliminary.  We should get far better
   // diagnostics for explaining buffer overruns.

diff  --git a/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
index 2d20e394681d45..361a4eed922108 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
@@ -24,7 +24,7 @@ using namespace ento;
 
 namespace {
   class BoolAssignmentChecker : public Checker< check::Bind > {
-    mutable std::unique_ptr<BuiltinBug> BT;
+    mutable std::unique_ptr<BugType> BT;
     void emitReport(ProgramStateRef state, CheckerContext &C,
                     bool IsTainted = false) const;
 
@@ -37,7 +37,7 @@ void BoolAssignmentChecker::emitReport(ProgramStateRef state, CheckerContext &C,
                                        bool IsTainted) const {
   if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
     if (!BT)
-      BT.reset(new BuiltinBug(this, "Assignment of a non-Boolean value"));
+      BT.reset(new BugType(this, "Assignment of a non-Boolean value"));
 
     StringRef Msg = IsTainted ? "Might assign a tainted non-Boolean value"
                               : "Assignment of a non-Boolean value";

diff  --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 387edd8c3b1860..7d3aaac1ec0a84 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -653,13 +653,15 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
 void CStringChecker::emitNullArgBug(CheckerContext &C, ProgramStateRef State,
                                     const Stmt *S, StringRef WarningMsg) const {
   if (ExplodedNode *N = C.generateErrorNode(State)) {
-    if (!BT_Null)
-      BT_Null.reset(new BuiltinBug(
-          Filter.CheckNameCStringNullArg, categories::UnixAPI,
-          "Null pointer argument in call to byte string function"));
+    if (!BT_Null) {
+      // FIXME: This call uses the string constant 'categories::UnixAPI' as the
+      // description of the bug; it should be replaced by a real description.
+      BT_Null.reset(
+          new BugType(Filter.CheckNameCStringNullArg, categories::UnixAPI));
+    }
 
-    BuiltinBug *BT = static_cast<BuiltinBug *>(BT_Null.get());
-    auto Report = std::make_unique<PathSensitiveBugReport>(*BT, WarningMsg, N);
+    auto Report =
+        std::make_unique<PathSensitiveBugReport>(*BT_Null, WarningMsg, N);
     Report->addRange(S->getSourceRange());
     if (const auto *Ex = dyn_cast<Expr>(S))
       bugreporter::trackExpressionValue(N, Ex, *Report);
@@ -674,13 +676,11 @@ void CStringChecker::emitUninitializedReadBug(CheckerContext &C,
     const char *Msg =
         "Bytes string function accesses uninitialized/garbage values";
     if (!BT_UninitRead)
-      BT_UninitRead.reset(
-          new BuiltinBug(Filter.CheckNameCStringUninitializedRead,
-                         "Accessing unitialized/garbage values", Msg));
+      BT_UninitRead.reset(new BugType(Filter.CheckNameCStringUninitializedRead,
+                                      "Accessing unitialized/garbage values"));
 
-    BuiltinBug *BT = static_cast<BuiltinBug *>(BT_UninitRead.get());
-
-    auto Report = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
+    auto Report =
+        std::make_unique<PathSensitiveBugReport>(*BT_UninitRead, Msg, N);
     Report->addRange(E->getSourceRange());
     bugreporter::trackExpressionValue(N, E, *Report);
     C.emitReport(std::move(Report));
@@ -692,18 +692,16 @@ void CStringChecker::emitOutOfBoundsBug(CheckerContext &C,
                                         StringRef WarningMsg) const {
   if (ExplodedNode *N = C.generateErrorNode(State)) {
     if (!BT_Bounds)
-      BT_Bounds.reset(new BuiltinBug(
-          Filter.CheckCStringOutOfBounds ? Filter.CheckNameCStringOutOfBounds
-                                         : Filter.CheckNameCStringNullArg,
-          "Out-of-bound array access",
-          "Byte string function accesses out-of-bound array element"));
-
-    BuiltinBug *BT = static_cast<BuiltinBug *>(BT_Bounds.get());
+      BT_Bounds.reset(new BugType(Filter.CheckCStringOutOfBounds
+                                      ? Filter.CheckNameCStringOutOfBounds
+                                      : Filter.CheckNameCStringNullArg,
+                                  "Out-of-bound array access"));
 
     // FIXME: It would be nice to eventually make this diagnostic more clear,
     // e.g., by referencing the original declaration or by saying *why* this
     // reference is outside the range.
-    auto Report = std::make_unique<PathSensitiveBugReport>(*BT, WarningMsg, N);
+    auto Report =
+        std::make_unique<PathSensitiveBugReport>(*BT_Bounds, WarningMsg, N);
     Report->addRange(S->getSourceRange());
     C.emitReport(std::move(Report));
   }
@@ -713,10 +711,12 @@ void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State,
                                        const Stmt *S,
                                        StringRef WarningMsg) const {
   if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) {
-    if (!BT_NotCString)
-      BT_NotCString.reset(new BuiltinBug(
-          Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,
-          "Argument is not a null-terminated string."));
+    if (!BT_NotCString) {
+      // FIXME: This call uses the string constant 'categories::UnixAPI' as the
+      // description of the bug; it should be replaced by a real description.
+      BT_NotCString.reset(
+          new BugType(Filter.CheckNameCStringNotNullTerm, categories::UnixAPI));
+    }
 
     auto Report =
         std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N);
@@ -729,10 +729,13 @@ void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State,
 void CStringChecker::emitAdditionOverflowBug(CheckerContext &C,
                                              ProgramStateRef State) const {
   if (ExplodedNode *N = C.generateErrorNode(State)) {
-    if (!BT_AdditionOverflow)
+    if (!BT_AdditionOverflow) {
+      // FIXME: This call uses the word "API" as the description of the bug;
+      // it should be replaced by a better error message (if this unlikely
+      // situation continues to exist as a separate bug type).
       BT_AdditionOverflow.reset(
-          new BuiltinBug(Filter.CheckNameCStringOutOfBounds, "API",
-                         "Sum of expressions causes overflow."));
+          new BugType(Filter.CheckNameCStringOutOfBounds, "API"));
+    }
 
     // This isn't a great error message, but this should never occur in real
     // code anyway -- you'd have to create a buffer longer than a size_t can

diff  --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
index 79225e8e6ca312..ea74256935ca87 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -123,7 +123,7 @@ class CallAndMessageChecker
 
   void LazyInit_BT(const char *desc, std::unique_ptr<BugType> &BT) const {
     if (!BT)
-      BT.reset(new BuiltinBug(OriginalName, desc));
+      BT.reset(new BugType(OriginalName, desc));
   }
   bool uninitRefOrPointer(CheckerContext &C, const SVal &V,
                           SourceRange ArgRange, const Expr *ArgEx,
@@ -379,7 +379,7 @@ ProgramStateRef CallAndMessageChecker::checkFunctionPointerCall(
       return nullptr;
     }
     if (!BT_call_undef)
-      BT_call_undef.reset(new BuiltinBug(
+      BT_call_undef.reset(new BugType(
           OriginalName,
           "Called function pointer is an uninitialized pointer value"));
     emitBadCall(BT_call_undef.get(), C, Callee);
@@ -395,7 +395,7 @@ ProgramStateRef CallAndMessageChecker::checkFunctionPointerCall(
       return nullptr;
     }
     if (!BT_call_null)
-      BT_call_null.reset(new BuiltinBug(
+      BT_call_null.reset(new BugType(
           OriginalName, "Called function pointer is null (null dereference)"));
     emitBadCall(BT_call_null.get(), C, Callee);
     return nullptr;
@@ -450,7 +450,7 @@ ProgramStateRef CallAndMessageChecker::checkCXXMethodCall(
       return nullptr;
     }
     if (!BT_cxx_call_undef)
-      BT_cxx_call_undef.reset(new BuiltinBug(
+      BT_cxx_call_undef.reset(new BugType(
           OriginalName, "Called C++ object pointer is uninitialized"));
     emitBadCall(BT_cxx_call_undef.get(), C, CC->getCXXThisExpr());
     return nullptr;
@@ -466,7 +466,7 @@ ProgramStateRef CallAndMessageChecker::checkCXXMethodCall(
     }
     if (!BT_cxx_call_null)
       BT_cxx_call_null.reset(
-          new BuiltinBug(OriginalName, "Called C++ object pointer is null"));
+          new BugType(OriginalName, "Called C++ object pointer is null"));
     emitBadCall(BT_cxx_call_null.get(), C, CC->getCXXThisExpr());
     return nullptr;
   }
@@ -495,13 +495,13 @@ CallAndMessageChecker::checkCXXDeallocation(const CXXDeallocatorCall *DC,
     return nullptr;
   if (!BT_cxx_delete_undef)
     BT_cxx_delete_undef.reset(
-        new BuiltinBug(OriginalName, "Uninitialized argument value"));
+        new BugType(OriginalName, "Uninitialized argument value"));
   if (DE->isArrayFormAsWritten())
     Desc = "Argument to 'delete[]' is uninitialized";
   else
     Desc = "Argument to 'delete' is uninitialized";
-  BugType *BT = BT_cxx_delete_undef.get();
-  auto R = std::make_unique<PathSensitiveBugReport>(*BT, Desc, N);
+  auto R =
+      std::make_unique<PathSensitiveBugReport>(*BT_cxx_delete_undef, Desc, N);
   bugreporter::trackExpressionValue(N, DE, *R);
   C.emitReport(std::move(R));
   return nullptr;
@@ -585,21 +585,21 @@ void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
       switch (msg.getMessageKind()) {
       case OCM_Message:
         if (!BT_msg_undef)
-          BT_msg_undef.reset(new BuiltinBug(OriginalName,
-                                            "Receiver in message expression "
-                                            "is an uninitialized value"));
+          BT_msg_undef.reset(new BugType(OriginalName,
+                                         "Receiver in message expression "
+                                         "is an uninitialized value"));
         BT = BT_msg_undef.get();
         break;
       case OCM_PropertyAccess:
         if (!BT_objc_prop_undef)
-          BT_objc_prop_undef.reset(new BuiltinBug(
+          BT_objc_prop_undef.reset(new BugType(
               OriginalName,
               "Property access on an uninitialized object pointer"));
         BT = BT_objc_prop_undef.get();
         break;
       case OCM_Subscript:
         if (!BT_objc_subscript_undef)
-          BT_objc_subscript_undef.reset(new BuiltinBug(
+          BT_objc_subscript_undef.reset(new BugType(
               OriginalName,
               "Subscript access on an uninitialized object pointer"));
         BT = BT_objc_subscript_undef.get();
@@ -634,8 +634,8 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
   }
 
   if (!BT_msg_ret)
-    BT_msg_ret.reset(new BuiltinBug(OriginalName,
-                                    "Receiver in message expression is 'nil'"));
+    BT_msg_ret.reset(
+        new BugType(OriginalName, "Receiver in message expression is 'nil'"));
 
   const ObjCMessageExpr *ME = msg.getOriginExpr();
 

diff  --git a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
index 2d2e14de3f2baa..d1d4f3baf6a852 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
@@ -24,7 +24,7 @@ using namespace ento;
 
 namespace {
 class CastSizeChecker : public Checker< check::PreStmt<CastExpr> > {
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
 
 public:
   void checkPreStmt(const CastExpr *CE, CheckerContext &C) const;
@@ -132,11 +132,11 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
 
   if (ExplodedNode *errorNode = C.generateErrorNode()) {
     if (!BT)
-      BT.reset(new BuiltinBug(this, "Cast region with wrong size.",
-                                    "Cast a region whose size is not a multiple"
-                                    " of the destination type size."));
-    auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(),
-                                                      errorNode);
+      BT.reset(new BugType(this, "Cast region with wrong size."));
+    constexpr llvm::StringLiteral Msg =
+        "Cast a region whose size is not a multiple of the destination type "
+        "size.";
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, errorNode);
     R->addRange(CE->getSourceRange());
     C.emitReport(std::move(R));
   }

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 9ace1583eb538e..9e11d8d9ecbc3c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -41,7 +41,7 @@ bool isRootChanged(intptr_t k) { return k == ROOT_CHANGED; }
 //                      bug<--foo()--          JAIL_ENTERED<--foo()--
 class ChrootChecker : public Checker<eval::Call, check::PreCall> {
   // This bug refers to possibly break out of a chroot() jail.
-  mutable std::unique_ptr<BuiltinBug> BT_BreakJail;
+  mutable std::unique_ptr<BugType> BT_BreakJail;
 
   const CallDescription Chroot{{"chroot"}, 1}, Chdir{{"chdir"}, 1};
 
@@ -125,11 +125,11 @@ void ChrootChecker::checkPreCall(const CallEvent &Call,
     if (isRootChanged((intptr_t) *k))
       if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
         if (!BT_BreakJail)
-          BT_BreakJail.reset(new BuiltinBug(
-              this, "Break out of jail", "No call of chdir(\"/\") immediately "
-                                         "after chroot"));
-        C.emitReport(std::make_unique<PathSensitiveBugReport>(
-            *BT_BreakJail, BT_BreakJail->getDescription(), N));
+          BT_BreakJail.reset(new BugType(this, "Break out of jail"));
+        constexpr llvm::StringLiteral Msg =
+            "No call of chdir(\"/\") immediately after chroot";
+        C.emitReport(
+            std::make_unique<PathSensitiveBugReport>(*BT_BreakJail, Msg, N));
       }
 }
 

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
index 6ea39fb95e9a85..8b34b41bab21c3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
@@ -42,7 +42,7 @@ class ConversionChecker : public Checker<check::PreStmt<ImplicitCastExpr>> {
   void checkPreStmt(const ImplicitCastExpr *Cast, CheckerContext &C) const;
 
 private:
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
 
   bool isLossOfPrecision(const ImplicitCastExpr *Cast, QualType DestType,
                          CheckerContext &C) const;
@@ -127,8 +127,7 @@ void ConversionChecker::checkPreStmt(const ImplicitCastExpr *Cast,
 void ConversionChecker::reportBug(ExplodedNode *N, const Expr *E,
                                   CheckerContext &C, const char Msg[]) const {
   if (!BT)
-    BT.reset(
-        new BuiltinBug(this, "Conversion", "Possible loss of sign/precision."));
+    BT.reset(new BugType(this, "Conversion"));
 
   // Generate a report for this bug.
   auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);

diff  --git a/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
index 2fe91467c8c563..04bbe85473c0e0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
@@ -322,7 +322,7 @@ bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {
 namespace {
 
 class ReportStmts : public Checker<check::PreStmt<Stmt>> {
-  BuiltinBug BT_stmtLoc{this, "Statement"};
+  BugType BT_stmtLoc{this, "Statement"};
 
 public:
   void checkPreStmt(const Stmt *S, CheckerContext &C) const {

diff  --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
index bfb8d1cc010535..89be6a47250a24 100644
--- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
@@ -58,7 +58,7 @@ class ConstraintBasedEQEvaluator {
 // Being conservative, it does not warn if there is slight possibility the
 // value can be matching.
 class EnumCastOutOfRangeChecker : public Checker<check::PreStmt<CastExpr>> {
-  mutable std::unique_ptr<BuiltinBug> EnumValueCastOutOfRange;
+  mutable std::unique_ptr<BugType> EnumValueCastOutOfRange;
   void reportWarning(CheckerContext &C) const;
 
 public:
@@ -81,12 +81,12 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C) const {
   if (const ExplodedNode *N = C.generateNonFatalErrorNode()) {
     if (!EnumValueCastOutOfRange)
       EnumValueCastOutOfRange.reset(
-          new BuiltinBug(this, "Enum cast out of range",
-                         "The value provided to the cast expression is not in "
-                         "the valid range of values for the enum"));
+          new BugType(this, "Enum cast out of range"));
+    constexpr llvm::StringLiteral Msg =
+        "The value provided to the cast expression is not in the valid range"
+        " of values for the enum";
     C.emitReport(std::make_unique<PathSensitiveBugReport>(
-        *EnumValueCastOutOfRange, EnumValueCastOutOfRange->getDescription(),
-        N));
+        *EnumValueCastOutOfRange, Msg, N));
   }
 }
 

diff  --git a/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
index 6275e49e51ae47..2ee201b640089d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
@@ -24,7 +24,7 @@ using namespace ento;
 namespace {
 class FixedAddressChecker
   : public Checker< check::PreStmt<BinaryOperator> > {
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
 
 public:
   void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
@@ -49,14 +49,13 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
     return;
 
   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
+    // FIXME: improve grammar in the following strings:
     if (!BT)
-      BT.reset(
-          new BuiltinBug(this, "Use fixed address",
-                         "Using a fixed address is not portable because that "
-                         "address will probably not be valid in all "
-                         "environments or platforms."));
-    auto R =
-        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
+      BT.reset(new BugType(this, "Use fixed address"));
+    constexpr llvm::StringLiteral Msg =
+        "Using a fixed address is not portable because that address will "
+        "probably not be valid in all environments or platforms.";
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
     R->addRange(B->getRHS()->getSourceRange());
     C.emitReport(std::move(R));
   }

diff  --git a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
index fd47e19cb786c7..44b69ef31911c3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
@@ -303,7 +303,7 @@ std::unique_ptr<PathSensitiveBugReport>
 NonNullParamChecker::genReportReferenceToNullPointer(
     const ExplodedNode *ErrorNode, const Expr *ArgE) const {
   if (!BTNullRefArg)
-    BTNullRefArg.reset(new BuiltinBug(this, "Dereference of null pointer"));
+    BTNullRefArg.reset(new BugType(this, "Dereference of null pointer"));
 
   auto R = std::make_unique<PathSensitiveBugReport>(
       *BTNullRefArg, "Forming reference to null pointer", ErrorNode);

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
index a6383009e1feba..7906b787cd5346 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
@@ -25,8 +25,8 @@ using namespace ento;
 namespace {
 class ObjCAtSyncChecker
     : public Checker< check::PreStmt<ObjCAtSynchronizedStmt> > {
-  mutable std::unique_ptr<BuiltinBug> BT_null;
-  mutable std::unique_ptr<BuiltinBug> BT_undef;
+  mutable std::unique_ptr<BugType> BT_null;
+  mutable std::unique_ptr<BugType> BT_undef;
 
 public:
   void checkPreStmt(const ObjCAtSynchronizedStmt *S, CheckerContext &C) const;
@@ -44,8 +44,8 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
   if (isa<UndefinedVal>(V)) {
     if (ExplodedNode *N = C.generateErrorNode()) {
       if (!BT_undef)
-        BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex "
-                                            "for @synchronized"));
+        BT_undef.reset(new BugType(this, "Uninitialized value used as mutex "
+                                         "for @synchronized"));
       auto report = std::make_unique<PathSensitiveBugReport>(
           *BT_undef, BT_undef->getDescription(), N);
       bugreporter::trackExpressionValue(N, Ex, *report);
@@ -67,9 +67,9 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
       // a null mutex just means no synchronization occurs.
       if (ExplodedNode *N = C.generateNonFatalErrorNode(nullState)) {
         if (!BT_null)
-          BT_null.reset(new BuiltinBug(
-              this, "Nil value used as mutex for @synchronized() "
-                    "(no synchronization will occur)"));
+          BT_null.reset(
+              new BugType(this, "Nil value used as mutex for @synchronized() "
+                                "(no synchronization will occur)"));
         auto report = std::make_unique<PathSensitiveBugReport>(
             *BT_null, BT_null->getDescription(), N);
         bugreporter::trackExpressionValue(N, Ex, *report);

diff  --git a/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
index 27364eb72523d3..1d63c0dd01f3d6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
@@ -11,13 +11,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace clang;
 using namespace ento;
@@ -55,8 +56,8 @@ class PointerArithChecker
                                 bool PointedNeeded = false) const;
   void initAllocIdentifiers(ASTContext &C) const;
 
-  mutable std::unique_ptr<BuiltinBug> BT_pointerArith;
-  mutable std::unique_ptr<BuiltinBug> BT_polyArray;
+  mutable std::unique_ptr<BugType> BT_pointerArith;
+  mutable std::unique_ptr<BugType> BT_polyArray;
   mutable llvm::SmallSet<IdentifierInfo *, 8> AllocFunctions;
 
 public:
@@ -168,12 +169,11 @@ void PointerArithChecker::reportPointerArithMisuse(const Expr *E,
       return;
     if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
       if (!BT_polyArray)
-        BT_polyArray.reset(new BuiltinBug(
-            this, "Dangerous pointer arithmetic",
-            "Pointer arithmetic on a pointer to base class is dangerous "
-            "because derived and base class may have 
diff erent size."));
-      auto R = std::make_unique<PathSensitiveBugReport>(
-          *BT_polyArray, BT_polyArray->getDescription(), N);
+        BT_polyArray.reset(new BugType(this, "Dangerous pointer arithmetic"));
+      constexpr llvm::StringLiteral Msg =
+          "Pointer arithmetic on a pointer to base class is dangerous "
+          "because derived and base class may have 
diff erent size.";
+      auto R = std::make_unique<PathSensitiveBugReport>(*BT_polyArray, Msg, N);
       R->addRange(E->getSourceRange());
       R->markInteresting(ArrayRegion);
       C.emitReport(std::move(R));
@@ -191,12 +191,11 @@ void PointerArithChecker::reportPointerArithMisuse(const Expr *E,
 
   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
     if (!BT_pointerArith)
-      BT_pointerArith.reset(new BuiltinBug(this, "Dangerous pointer arithmetic",
-                                           "Pointer arithmetic on non-array "
-                                           "variables relies on memory layout, "
-                                           "which is dangerous."));
-    auto R = std::make_unique<PathSensitiveBugReport>(
-        *BT_pointerArith, BT_pointerArith->getDescription(), N);
+      BT_pointerArith.reset(new BugType(this, "Dangerous pointer arithmetic"));
+    constexpr llvm::StringLiteral Msg =
+        "Pointer arithmetic on non-array variables relies on memory layout, "
+        "which is dangerous.";
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT_pointerArith, Msg, N);
     R->addRange(SR);
     R->markInteresting(Region);
     C.emitReport(std::move(R));

diff  --git a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
index 81c19d9a094007..96d38eef3c03a0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -17,6 +17,7 @@
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace clang;
 using namespace ento;
@@ -24,7 +25,7 @@ using namespace ento;
 namespace {
 class PointerSubChecker
   : public Checker< check::PreStmt<BinaryOperator> > {
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
 
 public:
   void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
@@ -59,12 +60,11 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
 
   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
     if (!BT)
-      BT.reset(
-          new BuiltinBug(this, "Pointer subtraction",
-                         "Subtraction of two pointers that do not point to "
-                         "the same memory chunk may cause incorrect result."));
-    auto R =
-        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
+      BT.reset(new BugType(this, "Pointer subtraction"));
+    constexpr llvm::StringLiteral Msg =
+        "Subtraction of two pointers that do not point to the same memory "
+        "chunk may cause incorrect result.";
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
     R->addRange(B->getSourceRange());
     C.emitReport(std::move(R));
   }

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
index b85d0adb8eafb1..11dca1ff8831d0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
@@ -26,7 +26,7 @@ using namespace ento;
 namespace {
 class ReturnPointerRangeChecker :
     public Checker< check::PreStmt<ReturnStmt> > {
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
 
 public:
     void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
@@ -79,14 +79,13 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
     // FIXME: This bug correspond to CWE-466.  Eventually we should have bug
     // types explicitly reference such exploit categories (when applicable).
     if (!BT)
-      BT.reset(new BuiltinBug(
-          this, "Buffer overflow",
-          "Returned pointer value points outside the original object "
-          "(potential buffer overflow)"));
+      BT.reset(new BugType(this, "Buffer overflow"));
+    constexpr llvm::StringLiteral Msg =
+        "Returned pointer value points outside the original object "
+        "(potential buffer overflow)";
 
     // Generate a report for this bug.
-    auto Report =
-        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
+    auto Report = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
     Report->addRange(RetE->getSourceRange());
 
     const auto ConcreteElementCount = ElementCount.getAs<nonloc::ConcreteInt>();

diff  --git a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
index 5266cbf86b44f4..78cd0100bea42b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
@@ -24,8 +24,8 @@ using namespace ento;
 
 namespace {
 class ReturnUndefChecker : public Checker< check::PreStmt<ReturnStmt> > {
-  mutable std::unique_ptr<BuiltinBug> BT_Undef;
-  mutable std::unique_ptr<BuiltinBug> BT_NullReference;
+  mutable std::unique_ptr<BugType> BT_Undef;
+  mutable std::unique_ptr<BugType> BT_NullReference;
 
   void emitUndef(CheckerContext &C, const Expr *RetE) const;
   void checkReference(CheckerContext &C, const Expr *RetE,
@@ -77,14 +77,13 @@ void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
   }
 }
 
-static void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
-                    const Expr *TrackingE = nullptr) {
+static void emitBug(CheckerContext &C, BugType &BT, StringRef Msg,
+                    const Expr *RetE, const Expr *TrackingE = nullptr) {
   ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
 
-  auto Report =
-      std::make_unique<PathSensitiveBugReport>(BT, BT.getDescription(), N);
+  auto Report = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
 
   Report->addRange(RetE->getSourceRange());
   bugreporter::trackExpressionValue(N, TrackingE ? TrackingE : RetE, *Report);
@@ -94,10 +93,8 @@ static void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
 
 void ReturnUndefChecker::emitUndef(CheckerContext &C, const Expr *RetE) const {
   if (!BT_Undef)
-    BT_Undef.reset(
-        new BuiltinBug(this, "Garbage return value",
-                       "Undefined or garbage value returned to caller"));
-  emitBug(C, *BT_Undef, RetE);
+    BT_Undef.reset(new BugType(this, "Garbage return value"));
+  emitBug(C, *BT_Undef, "Undefined or garbage value returned to caller", RetE);
 }
 
 void ReturnUndefChecker::checkReference(CheckerContext &C, const Expr *RetE,
@@ -113,9 +110,10 @@ void ReturnUndefChecker::checkReference(CheckerContext &C, const Expr *RetE,
 
   // The return value is known to be null. Emit a bug report.
   if (!BT_NullReference)
-    BT_NullReference.reset(new BuiltinBug(this, "Returning null reference"));
+    BT_NullReference.reset(new BugType(this, "Returning null reference"));
 
-  emitBug(C, *BT_NullReference, RetE, bugreporter::getDerefExpr(RetE));
+  emitBug(C, *BT_NullReference, BT_NullReference->getDescription(), RetE,
+          bugreporter::getDerefExpr(RetE));
 }
 
 void ento::registerReturnUndefChecker(CheckerManager &mgr) {

diff  --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index abf9914f2ca4ed..19ff8c8e2a171a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -30,10 +30,10 @@ class StackAddrEscapeChecker
     : public Checker<check::PreCall, check::PreStmt<ReturnStmt>,
                      check::EndFunction> {
   mutable IdentifierInfo *dispatch_semaphore_tII = nullptr;
-  mutable std::unique_ptr<BuiltinBug> BT_stackleak;
-  mutable std::unique_ptr<BuiltinBug> BT_returnstack;
-  mutable std::unique_ptr<BuiltinBug> BT_capturedstackasync;
-  mutable std::unique_ptr<BuiltinBug> BT_capturedstackret;
+  mutable std::unique_ptr<BugType> BT_stackleak;
+  mutable std::unique_ptr<BugType> BT_returnstack;
+  mutable std::unique_ptr<BugType> BT_capturedstackasync;
+  mutable std::unique_ptr<BugType> BT_capturedstackret;
 
 public:
   enum CheckKind {
@@ -154,7 +154,7 @@ void StackAddrEscapeChecker::EmitStackError(CheckerContext &C,
   if (!N)
     return;
   if (!BT_returnstack)
-    BT_returnstack = std::make_unique<BuiltinBug>(
+    BT_returnstack = std::make_unique<BugType>(
         CheckNames[CK_StackAddrEscapeChecker],
         "Return of address to stack-allocated memory");
   // Generate a report for this bug.
@@ -194,7 +194,7 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
     if (!N)
       continue;
     if (!BT_capturedstackasync)
-      BT_capturedstackasync = std::make_unique<BuiltinBug>(
+      BT_capturedstackasync = std::make_unique<BugType>(
           CheckNames[CK_StackAddrAsyncEscapeChecker],
           "Address of stack-allocated memory is captured");
     SmallString<128> Buf;
@@ -218,7 +218,7 @@ void StackAddrEscapeChecker::checkReturnedBlockCaptures(
     if (!N)
       continue;
     if (!BT_capturedstackret)
-      BT_capturedstackret = std::make_unique<BuiltinBug>(
+      BT_capturedstackret = std::make_unique<BugType>(
           CheckNames[CK_StackAddrEscapeChecker],
           "Address of stack-allocated memory is captured");
     SmallString<128> Buf;
@@ -364,12 +364,9 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
     return;
 
   if (!BT_stackleak)
-    BT_stackleak = std::make_unique<BuiltinBug>(
-        CheckNames[CK_StackAddrEscapeChecker],
-        "Stack address stored into global variable",
-        "Stack address was saved into a global variable. "
-        "This is dangerous because the address will become "
-        "invalid after returning from the function");
+    BT_stackleak =
+        std::make_unique<BugType>(CheckNames[CK_StackAddrEscapeChecker],
+                                  "Stack address stored into global variable");
 
   for (const auto &P : Cb.V) {
     const MemRegion *Referrer = P.first;

diff  --git a/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
index 9d3a909f50c10c..5cdcc1075f444c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
@@ -78,7 +78,7 @@ class DivisionBRVisitor : public BugReporterVisitor {
 class TestAfterDivZeroChecker
     : public Checker<check::PreStmt<BinaryOperator>, check::BranchCondition,
                      check::EndFunction> {
-  mutable std::unique_ptr<BuiltinBug> DivZeroBug;
+  mutable std::unique_ptr<BugType> DivZeroBug;
   void reportBug(SVal Val, CheckerContext &C) const;
 
 public:
@@ -166,7 +166,7 @@ bool TestAfterDivZeroChecker::hasDivZeroMap(SVal Var,
 void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
   if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
     if (!DivZeroBug)
-      DivZeroBug.reset(new BuiltinBug(this, "Division by zero"));
+      DivZeroBug.reset(new BugType(this, "Division by zero"));
 
     auto R = std::make_unique<PathSensitiveBugReport>(
         *DivZeroBug, "Value being compared against zero has already been used "

diff  --git a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
index b17b983f034566..db886501a162d0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
@@ -27,7 +27,7 @@ using namespace ento;
 namespace {
 
 class UndefBranchChecker : public Checker<check::BranchCondition> {
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
 
   struct FindUndefExpr {
     ProgramStateRef St;
@@ -71,8 +71,8 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
     ExplodedNode *N = Ctx.generateErrorNode();
     if (N) {
       if (!BT)
-        BT.reset(new BuiltinBug(
-            this, "Branch condition evaluates to a garbage value"));
+        BT.reset(
+            new BugType(this, "Branch condition evaluates to a garbage value"));
 
       // What's going on here: we want to highlight the subexpression of the
       // condition that is the most likely source of the "uninitialized

diff  --git a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
index 2973dd5457c620..ecb6ed36ee40cb 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
@@ -72,7 +72,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
       if (ExplodedNode *N = C.generateErrorNode()) {
         if (!BT)
           BT.reset(
-              new BuiltinBug(this, "uninitialized variable captured by block"));
+              new BugType(this, "uninitialized variable captured by block"));
 
         // Generate a bug report.
         SmallString<128> buf;

diff  --git a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
index f20b38a53151c4..d8848b65fe884d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -92,7 +92,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
 
     if (!BT)
       BT.reset(
-          new BuiltinBug(this, "Result of operation is garbage or undefined"));
+          new BugType(this, "Result of operation is garbage or undefined"));
 
     SmallString<256> sbuf;
     llvm::raw_svector_ostream OS(sbuf);

diff  --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
index fdefe75e8201db..a6cc8cac8c9925 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
@@ -49,7 +49,7 @@ UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
   if (!N)
     return;
   if (!BT)
-    BT.reset(new BuiltinBug(this, "Array subscript is undefined"));
+    BT.reset(new BugType(this, "Array subscript is undefined"));
 
   // Generate a report for this bug.
   auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);

diff  --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
index 0fa3d6043971f4..4389ec3c1ae7c9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
@@ -53,7 +53,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
   static const char *const DefaultMsg =
       "Assigned value is garbage or undefined";
   if (!BT)
-    BT.reset(new BuiltinBug(this, DefaultMsg));
+    BT.reset(new BugType(this, DefaultMsg));
 
   // Generate a report for this bug.
   llvm::SmallString<128> Str;

diff  --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
index cd91fa9b090c32..3647c49cf3f97d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
@@ -38,14 +38,14 @@ namespace {
 
 class UninitializedObjectChecker
     : public Checker<check::EndFunction, check::DeadSymbols> {
-  std::unique_ptr<BuiltinBug> BT_uninitField;
+  std::unique_ptr<BugType> BT_uninitField;
 
 public:
   // The fields of this struct will be initialized when registering the checker.
   UninitObjCheckerOptions Opts;
 
   UninitializedObjectChecker()
-      : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {}
+      : BT_uninitField(new BugType(this, "Uninitialized fields")) {}
 
   void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;

diff  --git a/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
index 70e14b48a6efde..8a1e02748c9b2b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp
@@ -44,7 +44,7 @@ namespace {
 
 class VforkChecker : public Checker<check::PreCall, check::PostCall,
                                     check::Bind, check::PreStmt<ReturnStmt>> {
-  mutable std::unique_ptr<BuiltinBug> BT;
+  mutable std::unique_ptr<BugType> BT;
   mutable llvm::SmallSet<const IdentifierInfo *, 10> VforkAllowlist;
   mutable const IdentifierInfo *II_vfork = nullptr;
 
@@ -124,8 +124,7 @@ void VforkChecker::reportBug(const char *What, CheckerContext &C,
                              const char *Details) const {
   if (ExplodedNode *N = C.generateErrorNode(C.getState())) {
     if (!BT)
-      BT.reset(new BuiltinBug(this,
-                              "Dangerous construct in a vforked process"));
+      BT.reset(new BugType(this, "Dangerous construct in a vforked process"));
 
     SmallString<256> buf;
     llvm::raw_svector_ostream os(buf);

diff  --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index dc9820b61f1f62..9532254e3c4596 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2099,8 +2099,6 @@ PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const {
 
 void BugType::anchor() {}
 
-void BuiltinBug::anchor() {}
-
 //===----------------------------------------------------------------------===//
 // Methods for BugReport and subclasses.
 //===----------------------------------------------------------------------===//

diff  --git a/clang/unittests/StaticAnalyzer/CallEventTest.cpp b/clang/unittests/StaticAnalyzer/CallEventTest.cpp
index b1ae591eaf7ec5..5be25d2ada6738 100644
--- a/clang/unittests/StaticAnalyzer/CallEventTest.cpp
+++ b/clang/unittests/StaticAnalyzer/CallEventTest.cpp
@@ -36,11 +36,11 @@ void reportBug(const CheckerBase *Checker, const CallEvent &Call,
 }
 
 class CXXDeallocatorChecker : public Checker<check::PreCall> {
-  std::unique_ptr<BuiltinBug> BT_uninitField;
+  std::unique_ptr<BugType> BT_uninitField;
 
 public:
   CXXDeallocatorChecker()
-      : BT_uninitField(new BuiltinBug(this, "CXXDeallocator")) {}
+      : BT_uninitField(new BugType(this, "CXXDeallocator")) {}
 
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
     const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call);

diff  --git a/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp b/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
index 3f36a6494bd4a9..3e12eec549c4e7 100644
--- a/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
+++ b/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
@@ -26,7 +26,7 @@ namespace {
 
 class FalsePositiveGenerator : public Checker<eval::Call> {
   using Self = FalsePositiveGenerator;
-  const BuiltinBug FalsePositiveGeneratorBug{this, "FalsePositiveGenerator"};
+  const BugType FalsePositiveGeneratorBug{this, "FalsePositiveGenerator"};
   using HandlerFn = bool (Self::*)(const CallEvent &Call,
                                    CheckerContext &) const;
   CallDescriptionMap<HandlerFn> Callbacks = {

diff  --git a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
index 85cce190a65e9d..d5c7a5c9bb8233 100644
--- a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
+++ b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
@@ -89,8 +89,8 @@ TEST(RegisterCustomCheckers, CheckLocationIncDec) {
 
 class CheckerRegistrationOrderPrinter
     : public Checker<check::PreStmt<DeclStmt>> {
-  std::unique_ptr<BuiltinBug> BT =
-      std::make_unique<BuiltinBug>(this, "Registration order");
+  std::unique_ptr<BugType> BT =
+      std::make_unique<BugType>(this, "Registration order");
 
 public:
   void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
@@ -125,8 +125,7 @@ void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) {
 
 #define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG)                               \
   class CHECKER_NAME : public Checker<check::PreStmt<DeclStmt>> {              \
-    std::unique_ptr<BuiltinBug> BT =                                           \
-        std::make_unique<BuiltinBug>(this, DIAG_MSG);                          \
+    std::unique_ptr<BugType> BT = std::make_unique<BugType>(this, DIAG_MSG);   \
                                                                                \
   public:                                                                      \
     void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {}          \


        


More information about the cfe-commits mailing list