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

//===- unittests/Analysis/FlowSensitive/TransferTest.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
//
//===----------------------------------------------------------------------===//

#include "TestingSupport.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
#include "clang/Analysis/FlowSensitive/RecordOps.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Basic/LangStandard.h"
#include "clang/Testing/TestAST.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <optional>
#include <string>
#include <utility>

namespace clang {
namespace dataflow {
namespace {
AST_MATCHER(FunctionDecl, isTemplated) {}
} // namespace
} // namespace dataflow
} // namespace clang

namespace {

usingnamespaceclang;
usingnamespacedataflow;
usingnamespacetest;
Eq;
IsNull;
Ne;
NotNull;
UnorderedElementsAre;

// Declares a minimal coroutine library.
constexpr llvm::StringRef CoroutineLibrary =;

void runDataflow(
    llvm::StringRef Code,
    std::function<
        void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
             ASTContext &)>
        VerifyResults,
    DataflowAnalysisOptions Options,
    LangStandard::Kind Std = LangStandard::lang_cxx17,
    llvm::StringRef TargetFun = "target") {}

void runDataflow(
    llvm::StringRef Code,
    std::function<
        void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
             ASTContext &)>
        VerifyResults,
    LangStandard::Kind Std = LangStandard::lang_cxx17,
    bool ApplyBuiltinTransfer = true, llvm::StringRef TargetFun = "target") {}

void runDataflowOnLambda(
    llvm::StringRef Code,
    std::function<
        void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
             ASTContext &)>
        VerifyResults,
    DataflowAnalysisOptions Options,
    LangStandard::Kind Std = LangStandard::lang_cxx17) {}

void runDataflowOnLambda(
    llvm::StringRef Code,
    std::function<
        void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
             ASTContext &)>
        VerifyResults,
    LangStandard::Kind Std = LangStandard::lang_cxx17,
    bool ApplyBuiltinTransfer = true) {}

const Formula &getFormula(const ValueDecl &D, const Environment &Env) {}

TEST(TransferTest, CNotSupported) {}

TEST(TransferTest, ObjectiveCNotSupported) {}

TEST(TransferTest, ObjectiveCXXNotSupported) {}

TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {}

TEST(TransferTest, BoolVarDecl) {}

TEST(TransferTest, IntVarDecl) {}

TEST(TransferTest, StructIncomplete) {}

// As a memory optimization, we prevent modeling fields nested below a certain
// level (currently, depth 3). This test verifies this lack of modeling. We also
// include a regression test for the case that the unmodeled field is a
// reference to a struct; previously, we crashed when accessing such a field.
TEST(TransferTest, StructFieldUnmodeled) {}

TEST(TransferTest, StructVarDecl) {}

TEST(TransferTest, StructVarDeclWithInit) {}

TEST(TransferTest, StructArrayVarDecl) {}

TEST(TransferTest, ClassVarDecl) {}

TEST(TransferTest, ReferenceVarDecl) {}

TEST(TransferTest, SelfReferentialReferenceVarDecl) {}

TEST(TransferTest, PointerVarDecl) {}

TEST(TransferTest, SelfReferentialPointerVarDecl) {}

TEST(TransferTest, DirectlySelfReferentialReference) {}

TEST(TransferTest, MultipleVarsDecl) {}

TEST(TransferTest, JoinVarDecl) {}

TEST(TransferTest, BinaryOperatorAssign) {}

TEST(TransferTest, BinaryOperatorAssignIntegerLiteral) {}

TEST(TransferTest, VarDeclInitAssign) {}

TEST(TransferTest, VarDeclInitAssignChained) {}

TEST(TransferTest, VarDeclInitAssignPtrDeref) {}

TEST(TransferTest, AssignToAndFromReference) {}

TEST(TransferTest, MultipleParamDecls) {}

TEST(TransferTest, StructParamDecl) {}

TEST(TransferTest, ReferenceParamDecl) {}

TEST(TransferTest, PointerParamDecl) {}

TEST(TransferTest, StructMember) {}

TEST(TransferTest, StructMemberEnum) {}

TEST(TransferTest, DerivedBaseMemberClass) {}

static void derivedBaseMemberExpectations(
    const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
    ASTContext &ASTCtx) {}

TEST(TransferTest, DerivedBaseMemberStructDefault) {}

TEST(TransferTest, DerivedBaseMemberPrivateFriend) {}

TEST(TransferTest, ClassMember) {}

TEST(TransferTest, BaseClassInitializer) {}

TEST(TransferTest, FieldsDontHaveValuesInConstructor) {}

TEST(TransferTest, FieldsDontHaveValuesInConstructorWithBaseClass) {}

TEST(TransferTest, StructModeledFieldsWithAccessor) {}

TEST(TransferTest, StructModeledFieldsInTypeid) {}

TEST(TransferTest, StructModeledFieldsWithComplicatedInheritance) {}

TEST(TransferTest, StructInitializerListWithComplicatedInheritance) {}

TEST(TransferTest, ReferenceMember) {}

TEST(TransferTest, StructThisMember) {}

TEST(TransferTest, ClassThisMember) {}

TEST(TransferTest, UnionThisMember) {}

TEST(TransferTest, StructThisInLambda) {}

TEST(TransferTest, ConstructorInitializer) {}

TEST(TransferTest, DefaultInitializer) {}

TEST(TransferTest, DefaultInitializerReference) {}

TEST(TransferTest, TemporaryObject) {}

TEST(TransferTest, ElidableConstructor) {}

TEST(TransferTest, AssignmentOperator) {}

// It's legal for the assignment operator to take its source parameter by value.
// Check that we handle this correctly. (This is a repro -- we used to
// assert-fail on this.)
TEST(TransferTest, AssignmentOperator_ArgByValue) {}

TEST(TransferTest, AssignmentOperatorFromBase) {}

TEST(TransferTest, AssignmentOperatorFromCallResult) {}

TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {}

TEST(TransferTest, AssignmentOperatorReturnsVoid) {}

TEST(TransferTest, AssignmentOperatorReturnsByValue) {}

TEST(TransferTest, AssignmentOperatorReturnsDifferentTypeByRef) {}

TEST(TransferTest, AssignmentOperatorReturnsDifferentTypeByValue) {}

TEST(TransferTest, InitListExprAsXValue) {}

TEST(TransferTest, ArrayInitListExprOneRecordElement) {}

TEST(TransferTest, InitListExprAsUnion) {}

TEST(TransferTest, EmptyInitListExprForUnion) {}

TEST(TransferTest, EmptyInitListExprForStruct) {}

TEST(TransferTest, CopyConstructor) {}

TEST(TransferTest, CopyConstructorWithDefaultArgument) {}

TEST(TransferTest, CopyConstructorWithParens) {}

TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {}

TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {}

TEST(TransferTest, MoveConstructor) {}

TEST(TransferTest, BindTemporary) {}

TEST(TransferTest, ResultObjectLocation) {}

TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {}

TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {}

// This test ensures that CXXOperatorCallExpr returning prvalues are correctly
// handled by the transfer functions, especially that `getResultObjectLocation`
// correctly returns a storage location for those.
TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {}

TEST(TransferTest, ResultObjectLocationForInitListExpr) {}

TEST(TransferTest, ResultObjectLocationForParenInitListExpr) {}

// Check that the `std::strong_ordering` object returned by builtin `<=>` has a
// correctly modeled result object location.
TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {}

TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {}

TEST(TransferTest, ResultObjectLocationForStmtExpr) {}

TEST(TransferTest, ResultObjectLocationForBuiltinBitCastExpr) {}

TEST(TransferTest, ResultObjectLocationForAtomicExpr) {}

TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {}

TEST(TransferTest, ResultObjectLocationDontVisitNestedRecordDecl) {}

TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) {}

TEST(TransferTest, StaticCast) {}

TEST(TransferTest, IntegralCast) {}

TEST(TransferTest, IntegraltoBooleanCast) {}

TEST(TransferTest, IntegralToBooleanCastFromBool) {}

TEST(TransferTest, WidenBoolValueInIntegerVariable) {}

TEST(TransferTest, NullToPointerCast) {}

TEST(TransferTest, PointerToMemberVariable) {}

TEST(TransferTest, PointerToMemberFunction) {}

TEST(TransferTest, NullToMemberPointerCast) {}

TEST(TransferTest, AddrOfValue) {}

TEST(TransferTest, AddrOfReference) {}

TEST(TransferTest, Preincrement) {}

TEST(TransferTest, Postincrement) {}

// We test just one of the compound assignment operators because we know the
// code for propagating the storage location is shared among all of them.
TEST(TransferTest, AddAssign) {}

TEST(TransferTest, CannotAnalyzeFunctionTemplate) {}

TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {}

TEST(TransferTest, VarDeclInitAssignConditionalOperator) {}

TEST(TransferTest, VarDeclInDoWhile) {}

TEST(TransferTest, UnreachableAfterWhileTrue) {}

TEST(TransferTest, AggregateInitialization) {}

TEST(TransferTest, AggregateInitializationReferenceField) {}

TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {}

TEST(TransferTest, AggregateInitializationFunctionPointer) {}

TEST(TransferTest, AssignToUnionMember) {}

TEST(TransferTest, AssignFromBoolLiteral) {}

TEST(TransferTest, AssignFromCompositeBoolExpression) {}

TEST(TransferTest, AssignFromBoolNegation) {}

TEST(TransferTest, BuiltinExpect) {}

// `__builtin_expect` takes and returns a `long` argument, so other types
// involve casts. This verifies that we identify the input and output in that
// case.
TEST(TransferTest, BuiltinExpectBoolArg) {}

TEST(TransferTest, BuiltinUnreachable) {}

TEST(TransferTest, BuiltinTrap) {}

TEST(TransferTest, BuiltinDebugTrap) {}

TEST(TransferTest, StaticIntSingleVarDecl) {}

TEST(TransferTest, StaticIntGroupVarDecl) {}

TEST(TransferTest, GlobalIntVarDecl) {}

TEST(TransferTest, StaticMemberIntVarDecl) {}

TEST(TransferTest, StaticMemberRefVarDecl) {}

TEST(TransferTest, AssignMemberBeforeCopy) {}

TEST(TransferTest, BooleanEquality) {}

TEST(TransferTest, BooleanInequality) {}

TEST(TransferTest, PointerEquality) {}

TEST(TransferTest, PointerEqualityUnionMembers) {}

TEST(TransferTest, IntegerLiteralEquality) {}

TEST(TransferTest, CorrelatedBranches) {}

TEST(TransferTest, LoopWithAssignmentConverges) {}

TEST(TransferTest, LoopWithStagedAssignments) {}

TEST(TransferTest, LoopWithReferenceAssignmentConverges) {}

TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {}

TEST(TransferTest, LoopDereferencingChangingPointerConverges) {}

TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {}

TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {}

TEST(TransferTest, LoopCanProveInvariantForBoolean) {}

TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {}

TEST(TransferTest, DoesNotCrashOnNullChildren) {}

TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {}

TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {}

TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {}

TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {}

TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {}

TEST(TransferTest, BinaryOperatorComma) {}

TEST(TransferTest, ConditionalOperatorValue) {}

TEST(TransferTest, ConditionalOperatorLocation) {}

TEST(TransferTest, ConditionalOperatorOnConstantExpr) {}

TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {}

TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {}

TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {}

TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {}

TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {}

TEST(TransferTest, ContextSensitiveOptionDisabled) {}

TEST(TransferTest, ContextSensitiveReturnReference) {}

// This test is a regression test, based on a real crash.
TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {}

TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {}

TEST(TransferTest, ContextSensitiveDepthZero) {}

TEST(TransferTest, ContextSensitiveSetTrue) {}

TEST(TransferTest, ContextSensitiveSetFalse) {}

TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {}

TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {}

TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {}

TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {}

TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {}

TEST(TransferTest, ContextSensitiveMutualRecursion) {}

TEST(TransferTest, ContextSensitiveSetMultipleLines) {}

TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {}

TEST(TransferTest, ContextSensitiveReturnVoid) {}

TEST(TransferTest, ContextSensitiveReturnTrue) {}

TEST(TransferTest, ContextSensitiveReturnFalse) {}

TEST(TransferTest, ContextSensitiveReturnArg) {}

TEST(TransferTest, ContextSensitiveReturnInt) {}

TEST(TransferTest, ContextSensitiveReturnRecord) {}

TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {}

TEST(TransferTest, ContextSensitiveMethodLiteral) {}

TEST(TransferTest, ContextSensitiveMethodGetter) {}

TEST(TransferTest, ContextSensitiveMethodSetter) {}

TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {}


TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {}

TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {}

TEST(TransferTest, ContextSensitiveConstructorBody) {}

TEST(TransferTest, ContextSensitiveConstructorInitializer) {}

TEST(TransferTest, ContextSensitiveConstructorDefault) {}

TEST(TransferTest, ContextSensitiveSelfReferentialClass) {}

TEST(TransferTest, UnnamedBitfieldInitializer) {}

// Repro for a crash that used to occur with chained short-circuiting logical
// operators.
TEST(TransferTest, ChainedLogicalOps) {}

// Repro for a crash that used to occur when we call a `noreturn` function
// within one of the operands of a `&&` or `||` operator.
TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {}

TEST(TransferTest, NewExpressions) {}

TEST(TransferTest, NewExpressions_Structs) {}

TEST(TransferTest, FunctionToPointerDecayHasValue) {}

// Check that a builtin function is not associated with a value. (It's only
// possible to call builtin functions directly, not take their address.)
TEST(TransferTest, BuiltinFunctionModeled) {}

// Check that a callee of a member operator call is modeled as a `PointerValue`.
// Member operator calls are unusual in that their callee is a pointer that
// stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
// member functions, the callee is a `MemberExpr` (which does not have pointer
// type).
// We want to make sure that we produce a pointer value for the callee in this
// specific scenario and that its storage location is durable (for convergence).
TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {}

// Check that fields of anonymous records are modeled.
TEST(TransferTest, AnonymousStruct) {}

TEST(TransferTest, AnonymousStructWithInitializer) {}

TEST(TransferTest, AnonymousStructWithReferenceField) {}

TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {}

TEST(TransferTest, LambdaCaptureByCopy) {}

TEST(TransferTest, LambdaCaptureByReference) {}

TEST(TransferTest, LambdaCaptureWithInitializer) {}

TEST(TransferTest, LambdaCaptureByCopyImplicit) {}

TEST(TransferTest, LambdaCaptureByReferenceImplicit) {}

TEST(TransferTest, LambdaCaptureThis) {}

// This test verifies correct modeling of a relational dependency that goes
// through unmodeled functions (the simple `cond()` in this case).
TEST(TransferTest, ConditionalRelation) {}

// This is a crash repro.
// We used to crash while transferring `S().i` because Clang contained a bug
// causing the AST to be malformed.
TEST(TransferTest, AnonymousUnionMemberExprInTemplate) {}

} // namespace