[clang] [analyzer] Add std::variant checker (PR #66481)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 21 08:29:42 PDT 2023
================
@@ -0,0 +1,104 @@
+//===- TaggedUnionModeling.h -------------------------------------*- 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_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_H
+#define LLVM_CLANG_LIB_STATICANALYZER_CHECKER_VARIANTLIKETYPEMODELING_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 <numeric>
+
+namespace clang {
+namespace ento {
+namespace tagged_union_modeling {
+
+// The implementation of all these functions can be found in the file
+// StdVariantChecker.cpp under the same directory as this file.
+CallEventRef<> getCaller(const CallEvent &Call, CheckerContext &C);
+bool isCopyConstructorCall(const CallEvent &Call);
+bool isCopyAssignmentCall(const CallEvent &Call);
+bool isMoveAssignmentCall(const CallEvent &Call);
+bool isMoveConstructorCall(const CallEvent &Call);
+bool isStdType(const Type *Type, const std::string &TypeName);
+bool isStdVariant(const Type *Type);
+bool calledFromSystemHeader(const CallEvent &Call, CheckerContext &C);
+
+// When invalidating regions, we also have to follow that by invalidating the
+// corresponding custom data in the program state.
+template <class TypeMap>
+ProgramStateRef
+removeInformationStoredForDeadInstances(const CallEvent *Call,
+ ProgramStateRef State,
+ ArrayRef<const MemRegion *> Regions) {
+ // If we do not know anything about the call we shall not continue.
+ // If the call is happens within a system header it is implementation detail.
+ // We should not take it into consideration.
+ if (!Call || Call->isInSystemHeader())
+ return State;
+
+ for (const MemRegion *Region : Regions)
+ State = State->remove<TypeMap>(Region);
+
+ return State;
+}
+
+template <class TypeMap>
+void handleConstructorAndAssignment(const CallEvent &Call, CheckerContext &C,
+ const SVal &ThisSVal) {
+ ProgramStateRef State = Call.getState();
+
+ if (!State)
+ return;
+
+ auto ArgSVal = Call.getArgSVal(0);
+ const auto *ThisRegion = ThisSVal.getAsRegion();
+ const auto *ArgMemRegion = ArgSVal.getAsRegion();
+
+ // Make changes to the state according to type of constructor/assignment
+ bool IsCopy = isCopyConstructorCall(Call) || isCopyAssignmentCall(Call);
+ bool IsMove = isMoveConstructorCall(Call) || isMoveAssignmentCall(Call);
+ // First we handle copy and move operations
+ if (IsCopy || IsMove) {
+ const QualType *OtherQType = State->get<TypeMap>(ArgMemRegion);
+
+ // If the argument of a copy constructor or assignment is unknown then
+ // we will not know the argument of the copied to object.
+ if (!OtherQType) {
+ State = State->remove<TypeMap>(ThisRegion);
+ } else {
+ // When move semantics is used we can only know that the moved from
+ // object must be in a destructible state. Other usage of the object
+ // than destruction is undefined.
----------------
DonatNagyE wrote:
As a side project (in a separate commit) you could extend this checker with code that warns when a moved-from variant object is accessed.
https://github.com/llvm/llvm-project/pull/66481
More information about the cfe-commits
mailing list