[clang] [analyzer] Add std::variant checker (PR #66481)

via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 21 03:40:26 PDT 2023


================
@@ -0,0 +1,324 @@
+//===- StdVariantChecker.cpp -------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Type.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/CallDescription.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <optional>
+#include <string_view>
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace tagged_union_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType)
+
+namespace clang {
+namespace ento {
+namespace tagged_union_modeling {
+
+// Returns the CallEvent representing the caller of the function
+// It is needed because the CallEvent class does not contain enough information
+// to tell who called it. Checker context is needed.
+CallEventRef<> getCaller(const CallEvent &Call, const ProgramStateRef &State) {
+  const auto *CallLocationContext = Call.getLocationContext();
+  if (!CallLocationContext || CallLocationContext->inTopFrame())
+    return nullptr;
+
+  const auto *CallStackFrameContext = CallLocationContext->getStackFrame();
+  if (!CallStackFrameContext)
+    return nullptr;
+
+  CallEventManager &CEMgr = State->getStateManager().getCallEventManager();
+  return CEMgr.getCaller(CallStackFrameContext, State);
+}
+
+const CXXConstructorDecl *
+getConstructorDeclarationForCall(const CallEvent &Call) {
+  const auto *ConstructorCall = dyn_cast<CXXConstructorCall>(&Call);
+  if (!ConstructorCall)
+    return nullptr;
+
+  return ConstructorCall->getDecl();
+}
+
+bool isCopyConstructorCall(const CallEvent &Call) {
+  if (const CXXConstructorDecl *ConstructorDecl =
+          getConstructorDeclarationForCall(Call))
+    return ConstructorDecl->isCopyConstructor();
+  return false;
+}
+
+bool isCopyAssignmentCall(const CallEvent &Call) {
+  const Decl *CopyAssignmentDecl = Call.getDecl();
+
+  if (const auto *AsMethodDecl =
+          dyn_cast_or_null<CXXMethodDecl>(CopyAssignmentDecl))
+    return AsMethodDecl->isCopyAssignmentOperator();
+  return false;
+}
+
+bool isMoveConstructorCall(const CallEvent &Call) {
+  const CXXConstructorDecl *ConstructorDecl =
+      getConstructorDeclarationForCall(Call);
+  if (!ConstructorDecl)
+    return false;
+
+  return ConstructorDecl->isMoveConstructor();
+}
+
+bool isMoveAssignmentCall(const CallEvent &Call) {
+  const Decl *CopyAssignmentDecl = Call.getDecl();
+
+  const auto *AsMethodDecl =
+      dyn_cast_or_null<CXXMethodDecl>(CopyAssignmentDecl);
+  if (!AsMethodDecl)
+    return false;
+
+  return AsMethodDecl->isMoveAssignmentOperator();
+}
+
+bool isStdType(const Type *Type, llvm::StringRef TypeName) {
+  auto *Decl = Type->getAsRecordDecl();
+  if (!Decl)
+    return false;
+  return (Decl->getName() == TypeName) && Decl->isInStdNamespace();
+}
+
+bool isStdVariant(const Type *Type) {
+  return isStdType(Type, llvm::StringRef("variant"));
----------------
DonatNagyE wrote:

I don't think that you need to call the constructor `llvm::StringRef` explicitly. Also note that there is a subclass of `StringRef` called `llvm::StringLiteral` which calculates the length of a string literal in compile time (it's used as the type of `constexpr` variables) -- perhaps you'd want to use that.

https://github.com/llvm/llvm-project/pull/66481


More information about the cfe-commits mailing list