llvm/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp

//===- UncheckedOptionalAccessModelTest.cpp -------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// FIXME: Move this to clang/unittests/Analysis/FlowSensitive/Models.

#include "clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h"
#include "TestingSupport.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Frontend/TextDiagnostic.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <optional>
#include <string>
#include <utility>
#include <vector>

usingnamespaceclang;
usingnamespacedataflow;
usingnamespacetest;

ContainerEq;

// FIXME: Move header definitions in separate file(s).
static constexpr char CSDtdDefHeader[] =;

static constexpr char StdTypeTraitsHeader[] =;

static constexpr char AbslTypeTraitsHeader[] =;

static constexpr char StdStringHeader[] =;

static constexpr char StdUtilityHeader[] =;

static constexpr char StdInitializerListHeader[] =;

static constexpr char StdOptionalHeader[] =;

static constexpr char AbslOptionalHeader[] =;

static constexpr char BaseOptionalHeader[] =;

/// Replaces all occurrences of `Pattern` in `S` with `Replacement`.
static void ReplaceAllOccurrences(std::string &S, const std::string &Pattern,
                                  const std::string &Replacement) {}

struct OptionalTypeIdentifier {};

static raw_ostream &operator<<(raw_ostream &OS,
                               const OptionalTypeIdentifier &TypeId) {}

class UncheckedOptionalAccessTest
    : public ::testing::TestWithParam<OptionalTypeIdentifier> {};

INSTANTIATE_TEST_SUITE_P();

// Verifies that similarly-named types are ignored.
TEST_P(UncheckedOptionalAccessTest, NonTrackedOptionalType) {}

TEST_P(UncheckedOptionalAccessTest, EmptyFunctionBody) {}

TEST_P(UncheckedOptionalAccessTest, UnwrapUsingValueNoCheck) {}

TEST_P(UncheckedOptionalAccessTest, UnwrapUsingOperatorStarNoCheck) {}

TEST_P(UncheckedOptionalAccessTest, UnwrapUsingOperatorArrowNoCheck) {}

TEST_P(UncheckedOptionalAccessTest, HasValueCheck) {}

TEST_P(UncheckedOptionalAccessTest, OperatorBoolCheck) {}

TEST_P(UncheckedOptionalAccessTest, UnwrapFunctionCallResultNoCheck) {}

TEST_P(UncheckedOptionalAccessTest, DefaultConstructor) {}

TEST_P(UncheckedOptionalAccessTest, NulloptConstructor) {}

TEST_P(UncheckedOptionalAccessTest, NulloptConstructorWithSugaredType) {}

TEST_P(UncheckedOptionalAccessTest, InPlaceConstructor) {}

TEST_P(UncheckedOptionalAccessTest, ValueConstructor) {}

TEST_P(UncheckedOptionalAccessTest, ConvertibleOptionalConstructor) {}

TEST_P(UncheckedOptionalAccessTest, MakeOptional) {}

TEST_P(UncheckedOptionalAccessTest, ValueOr) {}

TEST_P(UncheckedOptionalAccessTest, ValueOrComparisonPointers) {}

TEST_P(UncheckedOptionalAccessTest, ValueOrComparisonIntegers) {}

TEST_P(UncheckedOptionalAccessTest, ValueOrComparisonStrings) {}

TEST_P(UncheckedOptionalAccessTest, ValueOrComparisonPointerToOptional) {}

TEST_P(UncheckedOptionalAccessTest, Emplace) {}

TEST_P(UncheckedOptionalAccessTest, Reset) {}

TEST_P(UncheckedOptionalAccessTest, ValueAssignment) {}

TEST_P(UncheckedOptionalAccessTest, OptionalConversionAssignment) {}

TEST_P(UncheckedOptionalAccessTest, NulloptAssignment) {}

TEST_P(UncheckedOptionalAccessTest, OptionalSwap) {}

TEST_P(UncheckedOptionalAccessTest, OptionalReturnedFromFuntionCall) {}

TEST_P(UncheckedOptionalAccessTest, StdSwap) {}

TEST_P(UncheckedOptionalAccessTest, SwapUnmodeledLocLeft) {}

TEST_P(UncheckedOptionalAccessTest, SwapUnmodeledLocRight) {}

TEST_P(UncheckedOptionalAccessTest, SwapUnmodeledValueLeftSet) {}

TEST_P(UncheckedOptionalAccessTest, SwapUnmodeledValueLeftUnset) {}

// fixme: use recursion instead of depth.
TEST_P(UncheckedOptionalAccessTest, SwapUnmodeledValueRightSet) {}

TEST_P(UncheckedOptionalAccessTest, SwapUnmodeledValueRightUnset) {}

TEST_P(UncheckedOptionalAccessTest, UniquePtrToOptional) {}

TEST_P(UncheckedOptionalAccessTest, UniquePtrToStructWithOptionalField) {}

TEST_P(UncheckedOptionalAccessTest, CallReturningOptional) {}


TEST_P(UncheckedOptionalAccessTest, EqualityCheckLeftSet) {}

TEST_P(UncheckedOptionalAccessTest, EqualityCheckRightSet) {}

TEST_P(UncheckedOptionalAccessTest, EqualityCheckVerifySetAfterEq) {}

TEST_P(UncheckedOptionalAccessTest, EqualityCheckLeftUnset) {}

TEST_P(UncheckedOptionalAccessTest, EqualityCheckRightUnset) {}

TEST_P(UncheckedOptionalAccessTest, EqualityCheckRightNullopt) {}

TEST_P(UncheckedOptionalAccessTest, EqualityCheckLeftNullopt) {}

TEST_P(UncheckedOptionalAccessTest, EqualityCheckRightValue) {}

TEST_P(UncheckedOptionalAccessTest, EqualityCheckLeftValue) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckLeftSet) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckRightSet) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckVerifySetAfterEq) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckLeftUnset) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckRightUnset) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckRightNullopt) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckLeftNullopt) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckRightValue) {}

TEST_P(UncheckedOptionalAccessTest, InequalityCheckLeftValue) {}

// Verifies that the model sees through aliases.
TEST_P(UncheckedOptionalAccessTest, WithAlias) {}

TEST_P(UncheckedOptionalAccessTest, OptionalValueOptional) {}

TEST_P(UncheckedOptionalAccessTest, NestedOptionalAssignValue) {}

TEST_P(UncheckedOptionalAccessTest, NestedOptionalAssignOptional) {}

// Tests that structs can be nested. We use an optional field because its easy
// to use in a test, but the type of the field shouldn't matter.
TEST_P(UncheckedOptionalAccessTest, OptionalValueStruct) {}

// FIXME: A case that we should handle but currently don't.
// When there is a field of type reference to non-optional, we may
// stop recursively creating storage locations.
// E.g., the field `second` below in `pair` should eventually lead to
// the optional `x` in `A`.
TEST_P(UncheckedOptionalAccessTest, NestedOptionalThroughNonOptionalRefField) {}

TEST_P(UncheckedOptionalAccessTest, OptionalValueInitialization) {}

// This test is aimed at the core model, not the diagnostic. It is a regression
// test against a crash when using non-trivial smart pointers, like
// `std::unique_ptr`. As such, it doesn't test the access itself, which would be
// ignored regardless because of `IgnoreSmartPointerDereference = true`, above.
TEST_P(UncheckedOptionalAccessTest, AssignThroughLvalueReferencePtr) {}

TEST_P(UncheckedOptionalAccessTest, CorrelatedBranches) {}

TEST_P(UncheckedOptionalAccessTest, JoinDistinctValues) {}

TEST_P(UncheckedOptionalAccessTest, AccessValueInLoop) {}

TEST_P(UncheckedOptionalAccessTest, ReassignValueInLoopWithCheckSafe) {}

TEST_P(UncheckedOptionalAccessTest, ReassignValueInLoopNoCheckUnsafe) {}

TEST_P(UncheckedOptionalAccessTest, ReassignValueInLoopToUnsetUnsafe) {}

TEST_P(UncheckedOptionalAccessTest, ReassignValueInLoopToSetUnsafe) {}

TEST_P(UncheckedOptionalAccessTest, ReassignValueInLoopToUnknownUnsafe) {}

TEST_P(UncheckedOptionalAccessTest, ReassignValueInLoopBadConditionUnsafe) {}

TEST_P(UncheckedOptionalAccessTest, StructuredBindingsFromStruct) {}

TEST_P(UncheckedOptionalAccessTest, StructuredBindingsFromTupleLikeType) {}

TEST_P(UncheckedOptionalAccessTest, CtorInitializerNullopt) {}

TEST_P(UncheckedOptionalAccessTest, CtorInitializerValue) {}

// This is regression test, it shouldn't crash.
TEST_P(UncheckedOptionalAccessTest, Bitfield) {}

TEST_P(UncheckedOptionalAccessTest, LambdaParam) {}

TEST_P(UncheckedOptionalAccessTest, LambdaCaptureByCopy) {}

TEST_P(UncheckedOptionalAccessTest, LambdaCaptureByReference) {}

TEST_P(UncheckedOptionalAccessTest, LambdaCaptureWithInitializer) {}

TEST_P(UncheckedOptionalAccessTest, LambdaCaptureByCopyImplicit) {}

TEST_P(UncheckedOptionalAccessTest, LambdaCaptureByReferenceImplicit) {}

TEST_P(UncheckedOptionalAccessTest, LambdaCaptureThis) {}

TEST_P(UncheckedOptionalAccessTest, LambdaCaptureStateNotPropagated) {}

TEST_P(UncheckedOptionalAccessTest, ClassDerivedFromOptional) {}

TEST_P(UncheckedOptionalAccessTest, ClassTemplateDerivedFromOptional) {}

TEST_P(UncheckedOptionalAccessTest, ClassDerivedPrivatelyFromOptional) {}

TEST_P(UncheckedOptionalAccessTest, ClassDerivedFromOptionalValueConstructor) {}

// FIXME: Add support for:
// - constructors (copy, move)
// - assignment operators (default, copy, move)
// - invalidation (passing optional by non-const reference/pointer)