blob: 83a3341d955a31e08ccad85de9b4ee95a12db5da [file] [log] [blame]
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -08001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
Sam McCallda398802023-06-27 01:57:22 -07005#ifndef CRUBIT_NULLABILITY_POINTER_NULLABILITY_LATTICE_H_
6#define CRUBIT_NULLABILITY_POINTER_NULLABILITY_LATTICE_H_
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -08007
Dmitri Gribenko742c4c32023-07-31 12:32:09 -07008#include <functional>
Googler2c9f53f2023-10-24 07:33:00 -07009#include <optional>
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080010#include <ostream>
11
Googlerf7154ea2023-12-11 09:30:25 -080012#include "absl/base/nullability.h"
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -080013#include "absl/container/flat_hash_map.h"
Googlerd4437312023-01-17 15:10:29 -080014#include "absl/log/check.h"
Sam McCalld127f932023-05-02 07:15:27 -070015#include "nullability/type_nullability.h"
Googlerca74c792023-11-08 11:27:22 -080016#include "clang/AST/DeclCXX.h"
Sam McCall74bf8642023-06-16 11:21:42 -070017#include "clang/AST/Expr.h"
Dani Ferreira Franco Moura0d0db1d2023-01-17 11:08:07 -080018#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
Googlerca74c792023-11-08 11:27:22 -080019#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080020#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
Googlerca74c792023-11-08 11:27:22 -080021#include "clang/Analysis/FlowSensitive/StorageLocation.h"
22#include "clang/Analysis/FlowSensitive/Value.h"
Googler2c9f53f2023-10-24 07:33:00 -070023#include "clang/Basic/LLVM.h"
24#include "llvm/ADT/FunctionExtras.h"
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080025
Sam McCall4f6be422023-06-27 02:51:22 -070026namespace clang::tidy::nullability {
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080027class PointerNullabilityLattice {
28 public:
Sam McCall74bf8642023-06-16 11:21:42 -070029 struct NonFlowSensitiveState {
Sam McCallc290df42024-04-02 11:28:44 -070030 // Nullability interpretation of types as set e.g. by per-file #pragmas.
31 TypeNullabilityDefaults Defaults;
32
Sam McCall74bf8642023-06-16 11:21:42 -070033 absl::flat_hash_map<const Expr *, TypeNullability> ExprToNullability;
34 // Overridden symbolic nullability for pointer-typed decls.
Sam McCalle644e1d2023-07-18 19:19:12 -070035 // These are set by PointerNullabilityAnalysis::assignNullabilityVariable,
Googler2c9f53f2023-10-24 07:33:00 -070036 // and take precedence over the declared type and over any result from
37 // ConcreteNullabilityOverride.
Googlerf7154ea2023-12-11 09:30:25 -080038 absl::flat_hash_map<absl::Nonnull<const ValueDecl *>,
39 PointerTypeNullability>
Sam McCall74bf8642023-06-16 11:21:42 -070040 DeclTopLevelNullability;
Googler2c9f53f2023-10-24 07:33:00 -070041 // Returns overriding concrete nullability for decls. This is set by
42 // PointerNullabilityAnalysis::assignNullabilityOverride, and the result, if
43 // present, takes precedence over the declared type.
44 llvm::unique_function<std::optional<const PointerTypeNullability *>(
45 const Decl &) const>
46 ConcreteNullabilityOverride = [](const Decl &) { return std::nullopt; };
Sam McCall74bf8642023-06-16 11:21:42 -070047 };
48
49 PointerNullabilityLattice(NonFlowSensitiveState &NFS) : NFS(NFS) {}
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -080050
Martin Brænnec92447f2024-06-04 13:17:06 -070051 absl::Nullable<const TypeNullability *> getTypeNullability(
Googlerf7154ea2023-12-11 09:30:25 -080052 absl::Nonnull<const Expr *> E) const {
Sam McCall74bf8642023-06-16 11:21:42 -070053 auto I = NFS.ExprToNullability.find(&dataflow::ignoreCFGOmittedNodes(*E));
54 return I == NFS.ExprToNullability.end() ? nullptr : &I->second;
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -080055 }
56
57 // If the `ExprToNullability` map already contains an entry for `E`, does
58 // nothing. Otherwise, inserts a new entry with key `E` and value computed by
59 // the provided GetNullability.
Googlerd4437312023-01-17 15:10:29 -080060 // Returns the (cached or computed) nullability.
Sam McCalld127f932023-05-02 07:15:27 -070061 const TypeNullability &insertExprNullabilityIfAbsent(
Googlerf7154ea2023-12-11 09:30:25 -080062 absl::Nonnull<const Expr *> E,
Martin Brænne93db8652024-02-28 01:59:48 -080063 const std::function<TypeNullability()> &GetNullability);
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -080064
Martin Brænnedd03ae82024-03-28 08:02:41 -070065 // Returns the `Value` associated with the `RecordStorageLocation` and
66 // `MethodDecl` of `CE`, creating one if it doesn't yet exist.
67 // The type of `CE` must be either a raw pointer or boolean.
68 absl::Nullable<dataflow::Value *> getConstMethodReturnValue(
Googlerca74c792023-11-08 11:27:22 -080069 const dataflow::RecordStorageLocation &RecordLoc,
Martin Brænne93db8652024-02-28 01:59:48 -080070 absl::Nonnull<const CallExpr *> CE, dataflow::Environment &Env);
Googlerca74c792023-11-08 11:27:22 -080071
Googlerd54739c2024-07-31 09:24:46 -070072 // Returns the `RecordStorageLocation` associated with the
73 // `RecordStorageLocation` and `MethodDecl` of `CE`, creating one if it
74 // doesn't yet exist. The type of `CE` must be a smart pointer.
75 absl::Nullable<dataflow::StorageLocation *>
76 getConstMethodReturnStorageLocation(
77 const dataflow::RecordStorageLocation &RecordLoc,
78 absl::Nonnull<const CallExpr *> CE, dataflow::Environment &Env);
79
Googlerca74c792023-11-08 11:27:22 -080080 void clearConstMethodReturnValues(
81 const dataflow::RecordStorageLocation &RecordLoc) {
82 ConstMethodReturnValues.erase(&RecordLoc);
83 }
84
Googlerd54739c2024-07-31 09:24:46 -070085 void clearConstMethodReturnStorageLocations(
86 const dataflow::RecordStorageLocation &RecordLoc) {
87 ConstMethodReturnStorageLocations.erase(&RecordLoc);
88 }
89
Googler0b222ba2023-11-03 08:02:58 -070090 // If nullability for the decl D has been overridden, patch N to reflect it.
91 // (N is the nullability of an access to D).
Googlerf7154ea2023-12-11 09:30:25 -080092 void overrideNullabilityFromDecl(absl::Nullable<const Decl *> D,
93 TypeNullability &N) const;
Sam McCall74bf8642023-06-16 11:21:42 -070094
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080095 bool operator==(const PointerNullabilityLattice &Other) const { return true; }
96
Martin Brænne0a9f5092024-03-28 07:54:25 -070097 dataflow::LatticeJoinEffect join(const PointerNullabilityLattice &Other);
Sam McCall74bf8642023-06-16 11:21:42 -070098
Sam McCallc290df42024-04-02 11:28:44 -070099 const TypeNullabilityDefaults &defaults() const { return NFS.Defaults; }
100
Sam McCall74bf8642023-06-16 11:21:42 -0700101 private:
102 // Owned by the PointerNullabilityAnalysis object, shared by all lattice
103 // elements within one analysis run.
104 NonFlowSensitiveState &NFS;
Googlerca74c792023-11-08 11:27:22 -0800105
106 // Maps a record storage location and const method to the value to return
107 // from that const method.
Martin Brænne0a9f5092024-03-28 07:54:25 -0700108 using ConstMethodReturnValuesType = llvm::SmallDenseMap<
Googlerca74c792023-11-08 11:27:22 -0800109 const dataflow::RecordStorageLocation *,
Martin Brænnedd03ae82024-03-28 08:02:41 -0700110 llvm::SmallDenseMap<const FunctionDecl *, dataflow::Value *>>;
Martin Brænne0a9f5092024-03-28 07:54:25 -0700111 ConstMethodReturnValuesType ConstMethodReturnValues;
Googlerd54739c2024-07-31 09:24:46 -0700112
113 // Maps a record storage location and const method to the record storage
114 // location to return from that const method.
115 using ConstMethodReturnStorageLocationsType = llvm::SmallDenseMap<
116 const dataflow::RecordStorageLocation *,
117 llvm::SmallDenseMap<const FunctionDecl *, dataflow::StorageLocation *>>;
118 ConstMethodReturnStorageLocationsType ConstMethodReturnStorageLocations;
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800119};
120
121inline std::ostream &operator<<(std::ostream &OS,
122 const PointerNullabilityLattice &) {
123 return OS << "noop";
124}
125
Sam McCall4f6be422023-06-27 02:51:22 -0700126} // namespace clang::tidy::nullability
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800127
Sam McCallda398802023-06-27 01:57:22 -0700128#endif // CRUBIT_NULLABILITY_POINTER_NULLABILITY_LATTICE_H_