[clang] [analyzer] Add std::variant checker (PR #66481)
Balazs Benics via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 18 00:30:29 PDT 2023
================
@@ -0,0 +1,312 @@
+//===- 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 "llvm/ADT/FoldingSet.h"
+
+#include "TaggedUnionModeling.h"
+
+using namespace clang;
+using namespace ento;
+using namespace variant_modeling;
+
+REGISTER_MAP_WITH_PROGRAMSTATE(VariantHeldTypeMap, const MemRegion *, QualType)
+
+namespace clang {
+namespace ento {
+namespace variant_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) {
+ return nullptr;
+ }
+
+ if (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) {
+ const CXXConstructorDecl *ConstructorDecl =
+ getConstructorDeclarationForCall(Call);
+ if (!ConstructorDecl) {
+ return false;
+ }
+ return ConstructorDecl->isCopyConstructor();
+}
+
+bool isCopyAssignmentCall(const CallEvent &Call) {
+ const Decl *CopyAssignmentDecl = Call.getDecl();
+ if (!CopyAssignmentDecl) {
+ return false;
+ }
+ const auto *AsMethodDecl = dyn_cast<CXXMethodDecl>(CopyAssignmentDecl);
+ if (!AsMethodDecl) {
+ return false;
+ }
+ return AsMethodDecl->isCopyAssignmentOperator();
+}
+
+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();
+ if (!CopyAssignmentDecl) {
+ return false;
+ }
+ const auto *AsMethodDecl = dyn_cast<CXXMethodDecl>(CopyAssignmentDecl);
+ if (!AsMethodDecl) {
+ return false;
+ }
+ return AsMethodDecl->isMoveAssignmentOperator();
+}
+
+const TemplateArgument &getFirstTemplateArgument(const CallEvent &Call) {
+ const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
+ const FunctionDecl *FD = CE->getDirectCallee();
+ assert(1 <= FD->getTemplateSpecializationArgs()->asArray().size() &&
+ "std::get should have at least 1 template argument!");
----------------
steakhal wrote:
`getTemplateSpecializationArgs` might return null;
You don't need the `asArray` to have a `size()`.
https://github.com/llvm/llvm-project/pull/66481
More information about the cfe-commits
mailing list