llvm/clang/lib/Analysis/Consumed.cpp

//===- Consumed.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
//
//===----------------------------------------------------------------------===//
//
// A intra-procedural analysis for checking consumed properties.  This is based,
// in part, on research on linear types.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/Analyses/Consumed.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <memory>
#include <optional>
#include <utility>

// TODO: Adjust states of args to constructors in the same way that arguments to
//       function calls are handled.
// TODO: Use information from tests in for- and while-loop conditional.
// TODO: Add notes about the actual and expected state for
// TODO: Correctly identify unreachable blocks when chaining boolean operators.
// TODO: Adjust the parser and AttributesList class to support lists of
//       identifiers.
// TODO: Warn about unreachable code.
// TODO: Switch to using a bitmap to track unreachable blocks.
// TODO: Handle variable definitions, e.g. bool valid = x.isValid();
//       if (valid) ...; (Deferred)
// TODO: Take notes on state transitions to provide better warning messages.
//       (Deferred)
// TODO: Test nested conditionals: A) Checking the same value multiple times,
//       and 2) Checking different values. (Deferred)

usingnamespaceclang;
usingnamespaceconsumed;

// Key method definition
ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() = default;

static SourceLocation getFirstStmtLoc(const CFGBlock *Block) {}

static SourceLocation getLastStmtLoc(const CFGBlock *Block) {}

static ConsumedState invertConsumedUnconsumed(ConsumedState State) {}

static bool isCallableInState(const CallableWhenAttr *CWAttr,
                              ConsumedState State) {}

static bool isConsumableType(const QualType &QT) {}

static bool isAutoCastType(const QualType &QT) {}

static bool isSetOnReadPtrType(const QualType &QT) {}

static bool isKnownState(ConsumedState State) {}

static bool isRValueRef(QualType ParamType) {}

static bool isTestingFunction(const FunctionDecl *FunDecl) {}

static ConsumedState mapConsumableAttrState(const QualType QT) {}

static ConsumedState
mapParamTypestateAttrState(const ParamTypestateAttr *PTAttr) {}

static ConsumedState
mapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr) {}

static ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr) {}

static StringRef stateToString(ConsumedState State) {}

static ConsumedState testsFor(const FunctionDecl *FunDecl) {}

namespace {

struct VarTestResult {};

} // namespace

namespace clang {
namespace consumed {

enum EffectiveOp {};

class PropagationInfo {};

} // namespace consumed
} // namespace clang

static void
setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo,
                    ConsumedState State) {}

namespace clang {
namespace consumed {

class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> {};

} // namespace consumed
} // namespace clang

void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) {}

// Create a new state for To, which is initialized to the state of From.
// If NS is not CS_None, sets the state of From to NS.
void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To,
                                   ConsumedState NS) {}

// Get the ConsumedState for From
ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) {}

// If we already have info for To then update it, otherwise create a new entry.
void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) {}

void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo,
                                           const FunctionDecl *FunDecl,
                                           SourceLocation BlameLoc) {}

// Factors out common behavior for function, method, and operator calls.
// Check parameters and set parameter state if necessary.
// Returns true if the state of ObjArg is set, or false otherwise.
bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg,
                                     const FunctionDecl *FunD) {}

void ConsumedStmtVisitor::propagateReturnType(const Expr *Call,
                                              const FunctionDecl *Fun) {}

void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) {}

void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) {}

void ConsumedStmtVisitor::VisitCastExpr(const CastExpr *Cast) {}

void ConsumedStmtVisitor::VisitCXXBindTemporaryExpr(
  const CXXBindTemporaryExpr *Temp) {}

void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) {}

void ConsumedStmtVisitor::VisitCXXMemberCallExpr(
    const CXXMemberCallExpr *Call) {}

void ConsumedStmtVisitor::VisitCXXOperatorCallExpr(
    const CXXOperatorCallExpr *Call) {}

void ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) {}

void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {}

void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
  const MaterializeTemporaryExpr *Temp) {}

void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {}

void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) {}

void ConsumedStmtVisitor::VisitReturnStmt(const ReturnStmt *Ret) {}

void ConsumedStmtVisitor::VisitUnaryOperator(const UnaryOperator *UOp) {}

// TODO: See if I need to check for reference types here.
void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) {}

static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test,
                               ConsumedStateMap *ThenStates,
                               ConsumedStateMap *ElseStates) {}

static void splitVarStateForIfBinOp(const PropagationInfo &PInfo,
                                    ConsumedStateMap *ThenStates,
                                    ConsumedStateMap *ElseStates) {}

bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock,
                                            const CFGBlock *TargetBlock) {}

void ConsumedBlockInfo::addInfo(
    const CFGBlock *Block, ConsumedStateMap *StateMap,
    std::unique_ptr<ConsumedStateMap> &OwnedStateMap) {}

void ConsumedBlockInfo::addInfo(const CFGBlock *Block,
                                std::unique_ptr<ConsumedStateMap> StateMap) {}

ConsumedStateMap* ConsumedBlockInfo::borrowInfo(const CFGBlock *Block) {}

void ConsumedBlockInfo::discardInfo(const CFGBlock *Block) {}

std::unique_ptr<ConsumedStateMap>
ConsumedBlockInfo::getInfo(const CFGBlock *Block) {}

bool ConsumedBlockInfo::isBackEdge(const CFGBlock *From, const CFGBlock *To) {}

bool ConsumedBlockInfo::isBackEdgeTarget(const CFGBlock *Block) {}

void ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc,
  ConsumedWarningsHandlerBase &WarningsHandler) const {}

void ConsumedStateMap::clearTemporaries() {}

ConsumedState ConsumedStateMap::getState(const VarDecl *Var) const {}

ConsumedState
ConsumedStateMap::getState(const CXXBindTemporaryExpr *Tmp) const {}

void ConsumedStateMap::intersect(const ConsumedStateMap &Other) {}

void ConsumedStateMap::intersectAtLoopHead(const CFGBlock *LoopHead,
  const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates,
  ConsumedWarningsHandlerBase &WarningsHandler) {}

void ConsumedStateMap::markUnreachable() {}

void ConsumedStateMap::setState(const VarDecl *Var, ConsumedState State) {}

void ConsumedStateMap::setState(const CXXBindTemporaryExpr *Tmp,
                                ConsumedState State) {}

void ConsumedStateMap::remove(const CXXBindTemporaryExpr *Tmp) {}

bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const {}

void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC,
                                                    const FunctionDecl *D) {}

bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock,
                                  const ConsumedStmtVisitor &Visitor) {}

void ConsumedAnalyzer::run(AnalysisDeclContext &AC) {}