blob: 2a27d8e2e665e61906eff7e60f5ab0553ff94140 [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>
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -08009#include <ostream>
10
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -080011#include "absl/container/flat_hash_map.h"
Googlerd4437312023-01-17 15:10:29 -080012#include "absl/log/check.h"
Sam McCalld127f932023-05-02 07:15:27 -070013#include "nullability/type_nullability.h"
Sam McCall74bf8642023-06-16 11:21:42 -070014#include "clang/AST/Expr.h"
Dani Ferreira Franco Moura0d0db1d2023-01-17 11:08:07 -080015#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080016#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
17
Sam McCall4f6be422023-06-27 02:51:22 -070018namespace clang::tidy::nullability {
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080019
20class PointerNullabilityLattice {
21 public:
Sam McCall74bf8642023-06-16 11:21:42 -070022 struct NonFlowSensitiveState {
23 absl::flat_hash_map<const Expr *, TypeNullability> ExprToNullability;
24 // Overridden symbolic nullability for pointer-typed decls.
Sam McCalle644e1d2023-07-18 19:19:12 -070025 // These are set by PointerNullabilityAnalysis::assignNullabilityVariable,
26 // and take precedence over the declared type.
Sam McCall74bf8642023-06-16 11:21:42 -070027 absl::flat_hash_map<const ValueDecl *, PointerTypeNullability>
28 DeclTopLevelNullability;
29 };
30
31 PointerNullabilityLattice(NonFlowSensitiveState &NFS) : NFS(NFS) {}
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -080032
Sam McCalld127f932023-05-02 07:15:27 -070033 const TypeNullability *getExprNullability(const Expr *E) const {
Sam McCall74bf8642023-06-16 11:21:42 -070034 auto I = NFS.ExprToNullability.find(&dataflow::ignoreCFGOmittedNodes(*E));
35 return I == NFS.ExprToNullability.end() ? nullptr : &I->second;
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -080036 }
37
38 // If the `ExprToNullability` map already contains an entry for `E`, does
39 // nothing. Otherwise, inserts a new entry with key `E` and value computed by
40 // the provided GetNullability.
Googlerd4437312023-01-17 15:10:29 -080041 // Returns the (cached or computed) nullability.
Sam McCalld127f932023-05-02 07:15:27 -070042 const TypeNullability &insertExprNullabilityIfAbsent(
43 const Expr *E, const std::function<TypeNullability()> &GetNullability) {
Googlerd4437312023-01-17 15:10:29 -080044 E = &dataflow::ignoreCFGOmittedNodes(*E);
Sam McCall74bf8642023-06-16 11:21:42 -070045 if (auto It = NFS.ExprToNullability.find(E);
46 It != NFS.ExprToNullability.end())
Googlerd4437312023-01-17 15:10:29 -080047 return It->second;
48 // Deliberately perform a separate lookup after calling GetNullability.
49 // It may invalidate iterators, e.g. inserting missing vectors for children.
Sam McCall74bf8642023-06-16 11:21:42 -070050 auto [Iterator, Inserted] =
51 NFS.ExprToNullability.insert({E, GetNullability()});
Googlerd4437312023-01-17 15:10:29 -080052 CHECK(Inserted) << "GetNullability inserted same " << E->getStmtClassName();
53 return Iterator->second;
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -080054 }
55
Sam McCall74bf8642023-06-16 11:21:42 -070056 // Returns overridden nullability information associated with a declaration.
57 // For now we only track top-level decl nullability symbolically.
58 const PointerTypeNullability *getDeclNullability(const ValueDecl *D) const {
59 auto It = NFS.DeclTopLevelNullability.find(D);
60 if (It == NFS.DeclTopLevelNullability.end()) return nullptr;
61 return &It->second;
62 }
63
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080064 bool operator==(const PointerNullabilityLattice &Other) const { return true; }
65
66 dataflow::LatticeJoinEffect join(const PointerNullabilityLattice &Other) {
67 return dataflow::LatticeJoinEffect::Unchanged;
68 }
Sam McCall74bf8642023-06-16 11:21:42 -070069
70 private:
71 // Owned by the PointerNullabilityAnalysis object, shared by all lattice
72 // elements within one analysis run.
73 NonFlowSensitiveState &NFS;
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080074};
75
76inline std::ostream &operator<<(std::ostream &OS,
77 const PointerNullabilityLattice &) {
78 return OS << "noop";
79}
80
Sam McCall4f6be422023-06-27 02:51:22 -070081} // namespace clang::tidy::nullability
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -080082
Sam McCallda398802023-06-27 01:57:22 -070083#endif // CRUBIT_NULLABILITY_POINTER_NULLABILITY_LATTICE_H_