blob: b950422ddec2e3ecb87364bc06b888d06b0b8dae [file] [log] [blame]
Wei Yi Tee543af742022-06-01 06:52:24 -07001// 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
Googler7f19b2b2023-05-01 09:44:57 -07005#include "nullability/pointer_nullability_analysis.h"
Wei Yi Tee543af742022-06-01 06:52:24 -07006
Googlerbad70522023-01-31 04:37:38 -08007#include <optional>
Wei Yi Tee543af742022-06-01 06:52:24 -07008#include <string>
Martin Brænne66bc2432023-04-18 23:48:49 -07009#include <vector>
Wei Yi Tee543af742022-06-01 06:52:24 -070010
Lukasz Anforowicz2c34cae2022-08-26 07:19:20 -070011#include "absl/log/check.h"
Googler7f19b2b2023-05-01 09:44:57 -070012#include "nullability/pointer_nullability.h"
13#include "nullability/pointer_nullability_lattice.h"
14#include "nullability/pointer_nullability_matchers.h"
Sam McCall5fc2a802023-05-02 05:41:27 -070015#include "nullability/type_nullability.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070016#include "clang/AST/ASTContext.h"
Googlerd4437312023-01-17 15:10:29 -080017#include "clang/AST/ASTDumper.h"
Martin Brænneef1c7af2023-06-29 06:13:27 -070018#include "clang/AST/DeclTemplate.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070019#include "clang/AST/Expr.h"
Wei Yi Tee1cd62af2022-06-09 00:56:46 -070020#include "clang/AST/OperationKinds.h"
21#include "clang/AST/Stmt.h"
22#include "clang/AST/Type.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070023#include "clang/ASTMatchers/ASTMatchFinder.h"
Martin Brænnec4903062023-04-24 23:40:36 -070024#include "clang/ASTMatchers/ASTMatchers.h"
Wei Yi Tee217eb5f2022-09-15 03:18:28 -070025#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070026#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070027#include "clang/Analysis/FlowSensitive/Value.h"
28#include "clang/Basic/LLVM.h"
Wei Yi Teef5e8e572022-08-02 11:31:12 -070029#include "clang/Basic/Specifiers.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070030
Sam McCall4f6be422023-06-27 02:51:22 -070031namespace clang::tidy::nullability {
Wei Yi Tee543af742022-06-01 06:52:24 -070032
33using ast_matchers::MatchFinder;
34using dataflow::BoolValue;
Wei Yi Tee217eb5f2022-09-15 03:18:28 -070035using dataflow::CFGMatchSwitchBuilder;
Wei Yi Tee543af742022-06-01 06:52:24 -070036using dataflow::Environment;
Wei Yi Tee721ee972022-08-11 01:14:54 -070037using dataflow::PointerValue;
Wei Yi Tee543af742022-06-01 06:52:24 -070038using dataflow::TransferState;
39using dataflow::Value;
40
41namespace {
42
Sam McCall7d9afee2023-06-27 01:43:24 -070043TypeNullability prepend(NullabilityKind Head, const TypeNullability &Tail) {
Sam McCalld127f932023-05-02 07:15:27 -070044 TypeNullability Result = {Head};
Googler2bccf742023-01-18 03:53:14 -080045 Result.insert(Result.end(), Tail.begin(), Tail.end());
46 return Result;
47}
48
Sam McCall7d9afee2023-06-27 01:43:24 -070049void computeNullability(const Expr *E,
50 TransferState<PointerNullabilityLattice> &State,
Sam McCalld127f932023-05-02 07:15:27 -070051 std::function<TypeNullability()> Compute) {
Googler5ef1bdf2023-01-18 04:01:15 -080052 (void)State.Lattice.insertExprNullabilityIfAbsent(E, [&] {
53 auto Nullability = Compute();
54 if (unsigned ExpectedSize = countPointersInType(E);
55 ExpectedSize != Nullability.size()) {
56 // A nullability vector must have one entry per pointer in the type.
57 // If this is violated, we probably failed to handle some AST node.
Martin Brænne9d2afac2023-04-06 05:20:46 -070058 llvm::dbgs()
59 << "=== Nullability vector has wrong number of entries: ===\n";
Googler5ef1bdf2023-01-18 04:01:15 -080060 llvm::dbgs() << "Expression: \n";
61 dump(E, llvm::dbgs());
62 llvm::dbgs() << "\nNullability (" << Nullability.size()
63 << " pointers): " << nullabilityToString(Nullability)
64 << "\n";
65 llvm::dbgs() << "\nType (" << ExpectedSize << " pointers): \n";
66 dump(exprType(E), llvm::dbgs());
67 llvm::dbgs() << "=================================\n";
68
69 // We can't meaningfully interpret the vector, so discard it.
70 // TODO: fix all broken cases and upgrade to CHECK or DCHECK or so.
71 Nullability.assign(ExpectedSize, NullabilityKind::Unspecified);
72 }
73 return Nullability;
74 });
75}
76
Sam McCall5fc2a802023-05-02 05:41:27 -070077// Returns the computed nullability for a subexpr of the current expression.
78// This is always available as we compute bottom-up.
Sam McCall7d9afee2023-06-27 01:43:24 -070079const TypeNullability &getNullabilityForChild(
80 const Expr *E, TransferState<PointerNullabilityLattice> &State) {
Sam McCall5fc2a802023-05-02 05:41:27 -070081 return State.Lattice.insertExprNullabilityIfAbsent(E, [&] {
82 // Since we process child nodes before parents, we should already have
83 // computed the child nullability. However, this is not true in all test
84 // cases. So, we return unspecified nullability annotations.
85 // TODO: fix this issue, and CHECK() instead.
86 llvm::dbgs() << "=== Missing child nullability: ===\n";
87 dump(E, llvm::dbgs());
88 llvm::dbgs() << "==================================\n";
89
90 return unspecifiedNullability(E);
91 });
92}
93
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -080094/// Compute the nullability annotation of type `T`, which contains types
95/// originally written as a class template type parameter.
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -080096///
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -080097/// Example:
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -080098///
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -080099/// \code
100/// template <typename F, typename S>
101/// struct pair {
102/// S *_Nullable getNullablePtrToSecond();
103/// };
104/// \endcode
105///
106/// Consider the following member call:
107///
108/// \code
109/// pair<int *, int *_Nonnull> x;
110/// x.getNullablePtrToSecond();
111/// \endcode
112///
113/// The class template specialization `x` has the following substitutions:
114///
115/// F=int *, whose nullability is [_Unspecified]
116/// S=int * _Nonnull, whose nullability is [_Nonnull]
117///
118/// The return type of the member call `x.getNullablePtrToSecond()` is
119/// S * _Nullable.
120///
121/// When we call `substituteNullabilityAnnotationsInClassTemplate` with the type
122/// `S * _Nullable` and the `base` node of the member call (in this case, a
123/// `DeclRefExpr`), it returns the nullability of the given type after applying
124/// substitutions, which in this case is [_Nullable, _Nonnull].
Sam McCalld127f932023-05-02 07:15:27 -0700125TypeNullability substituteNullabilityAnnotationsInClassTemplate(
Sam McCall7d9afee2023-06-27 01:43:24 -0700126 QualType T, const TypeNullability &BaseNullabilityAnnotations,
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -0800127 QualType BaseType) {
Sam McCall932b7432023-01-23 04:41:22 -0800128 return getNullabilityAnnotationsFromType(
129 T,
Sam McCall7d9afee2023-06-27 01:43:24 -0700130 [&](const SubstTemplateTypeParmType *ST)
Sam McCalld127f932023-05-02 07:15:27 -0700131 -> std::optional<TypeNullability> {
Sam McCall28ab01a2023-01-23 05:15:48 -0800132 // The class specialization that is BaseType and owns ST.
Sam McCall7d9afee2023-06-27 01:43:24 -0700133 const ClassTemplateSpecializationDecl *Specialization = nullptr;
Sam McCall28ab01a2023-01-23 05:15:48 -0800134 if (auto RT = BaseType->getAs<RecordType>())
135 Specialization =
136 dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
137 // TODO: handle nested templates, where associated decl != base type
138 // (e.g. PointerNullabilityTest.MemberFunctionTemplateOfTemplateStruct)
139 if (!Specialization || Specialization != ST->getAssociatedDecl())
140 return std::nullopt;
Martin Brænneef1c7af2023-06-29 06:13:27 -0700141 // TODO: The code below does not deal correctly with partial
142 // specializations. We should eventually handle these, but for now, just
143 // bail out.
144 if (isa<ClassTemplatePartialSpecializationDecl>(
145 ST->getReplacedParameter()->getDeclContext()))
146 return std::nullopt;
Sam McCall28ab01a2023-01-23 05:15:48 -0800147
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800148 unsigned ArgIndex = ST->getIndex();
Sam McCall28ab01a2023-01-23 05:15:48 -0800149 auto TemplateArgs = Specialization->getTemplateArgs().asArray();
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800150
Sam McCalla45d2602023-04-28 13:20:15 -0700151 unsigned PointerCount =
152 countPointersInType(Specialization->getDeclContext());
Sam McCall28ab01a2023-01-23 05:15:48 -0800153 for (auto TA : TemplateArgs.take_front(ArgIndex)) {
154 PointerCount += countPointersInType(TA);
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800155 }
Sam McCall28ab01a2023-01-23 05:15:48 -0800156 unsigned SliceSize = countPointersInType(TemplateArgs[ArgIndex]);
Sam McCalld127f932023-05-02 07:15:27 -0700157 return ArrayRef(BaseNullabilityAnnotations)
158 .slice(PointerCount, SliceSize)
159 .vec();
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800160 });
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800161}
162
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800163/// Compute nullability annotations of `T`, which might contain template type
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800164/// variable substitutions bound by the call `CE`.
165///
166/// Example:
167///
168/// \code
169/// template<typename F, typename S>
170/// std::pair<S, F> flip(std::pair<F, S> p);
171/// \endcode
172///
173/// Consider the following CallExpr:
174///
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800175/// \code
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800176/// flip<int * _Nonnull, int * _Nullable>(std::make_pair(&x, &y));
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800177/// \endcode
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800178///
179/// This CallExpr has the following substitutions:
180/// F=int * _Nonnull, whose nullability is [_Nonnull]
181/// S=int * _Nullable, whose nullability is [_Nullable]
182///
183/// The return type of this CallExpr is `std::pair<S, F>`.
184///
185/// When we call `substituteNullabilityAnnotationsInFunctionTemplate` with the
186/// type `std::pair<S, F>` and the above CallExpr, it returns the nullability
187/// the given type after applying substitutions, which in this case is
188/// [_Nullable, _Nonnull].
Sam McCalld127f932023-05-02 07:15:27 -0700189TypeNullability substituteNullabilityAnnotationsInFunctionTemplate(
Sam McCall7d9afee2023-06-27 01:43:24 -0700190 QualType T, const CallExpr *CE) {
Sam McCall932b7432023-01-23 04:41:22 -0800191 return getNullabilityAnnotationsFromType(
192 T,
Sam McCall7d9afee2023-06-27 01:43:24 -0700193 [&](const SubstTemplateTypeParmType *ST)
Sam McCalld127f932023-05-02 07:15:27 -0700194 -> std::optional<TypeNullability> {
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800195 // TODO: Handle calls that use template argument deduction.
Lukasz Anforowicz60ed6c82023-04-26 12:05:26 -0700196 // TODO: Handle nested templates (...->getDepth() > 0).
Sam McCall7d9afee2023-06-27 01:43:24 -0700197 if (auto *DRE =
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800198 dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreImpCasts());
Martin Brænnec4903062023-04-24 23:40:36 -0700199 DRE != nullptr && ST->getReplacedParameter()->getDepth() == 0 &&
Martin Brænne8cdb0b12023-04-27 03:47:50 -0700200 // Some or all of the template arguments may be deduced, and we
201 // won't see those on the `DeclRefExpr`. If the template argument
202 // was deduced, we don't have any sugar for it.
Martin Brænne684cf702023-04-28 04:36:23 -0700203 // TODO(b/268348533): Can we somehow obtain it from the function
204 // param it was deduced from?
205 // TODO(b/268345783): This check, as well as the index into
206 // `template_arguments` below, may be incorrect in the presence of
207 // parameters packs. In function templates, parameter packs may
208 // appear anywhere in the parameter list. The index may therefore
209 // refer to one of the pack arguments, but we might incorrectly
210 // interpret it as referring to an argument that follows the pack.
Martin Brænne8cdb0b12023-04-27 03:47:50 -0700211 ST->getIndex() < DRE->template_arguments().size()) {
Sam McCall7d9afee2023-06-27 01:43:24 -0700212 TypeSourceInfo *TSI =
Martin Brænne61d4e362023-04-27 01:07:59 -0700213 DRE->template_arguments()[ST->getIndex()].getTypeSourceInfo();
214 if (TSI == nullptr) return std::nullopt;
215 return getNullabilityAnnotationsFromType(TSI->getType());
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800216 }
Sam McCall932b7432023-01-23 04:41:22 -0800217 return std::nullopt;
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800218 });
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -0800219}
220
Sam McCall7d9afee2023-06-27 01:43:24 -0700221NullabilityKind getPointerNullability(const Expr *E,
222 PointerNullabilityAnalysis::Lattice &L) {
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800223 QualType ExprType = E->getType();
Googlerbad70522023-01-31 04:37:38 -0800224 std::optional<NullabilityKind> Nullability = ExprType->getNullability();
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800225
226 // If the expression's type does not contain nullability information, it may
227 // be a template instantiation. Look up the nullability in the
228 // `ExprToNullability` map.
229 if (Nullability.value_or(NullabilityKind::Unspecified) ==
230 NullabilityKind::Unspecified) {
231 if (auto MaybeNullability = L.getExprNullability(E)) {
232 if (!MaybeNullability->empty()) {
233 // Return the nullability of the topmost pointer in the type.
234 Nullability = (*MaybeNullability)[0];
235 }
236 }
237 }
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800238 return Nullability.value_or(NullabilityKind::Unspecified);
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800239}
240
Dani Ferreira Franco Moura1d41c112022-12-21 08:43:32 -0800241void initPointerFromAnnotations(
Sam McCall7d9afee2023-06-27 01:43:24 -0700242 PointerValue &PointerVal, const Expr *E,
243 TransferState<PointerNullabilityLattice> &State) {
Dani Ferreira Franco Moura1d41c112022-12-21 08:43:32 -0800244 NullabilityKind Nullability = getPointerNullability(E, State.Lattice);
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700245 switch (Nullability) {
246 case NullabilityKind::NonNull:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800247 initNotNullPointer(PointerVal, State.Env);
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700248 break;
Wei Yi Teeae43f392022-08-02 11:33:23 -0700249 case NullabilityKind::Nullable:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800250 initNullablePointer(PointerVal, State.Env);
Wei Yi Teeae43f392022-08-02 11:33:23 -0700251 break;
252 default:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800253 initUnknownPointer(PointerVal, State.Env);
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700254 }
255}
256
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800257void transferFlowSensitiveNullPointer(
Sam McCall7d9afee2023-06-27 01:43:24 -0700258 const Expr *NullPointer, const MatchFinder::MatchResult &,
259 TransferState<PointerNullabilityLattice> &State) {
260 if (auto *PointerVal = getPointerValueFromExpr(NullPointer, State.Env)) {
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700261 initNullPointer(*PointerVal, State.Env);
262 }
263}
264
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800265void transferFlowSensitiveNotNullPointer(
Sam McCall7d9afee2023-06-27 01:43:24 -0700266 const Expr *NotNullPointer, const MatchFinder::MatchResult &,
267 TransferState<PointerNullabilityLattice> &State) {
268 if (auto *PointerVal = getPointerValueFromExpr(NotNullPointer, State.Env)) {
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700269 initNotNullPointer(*PointerVal, State.Env);
270 }
271}
272
Sam McCall7d9afee2023-06-27 01:43:24 -0700273const PointerTypeNullability *getOverriddenNullability(
274 const Expr *E, PointerNullabilityLattice &Lattice) {
275 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
Sam McCall74bf8642023-06-16 11:21:42 -0700276 return Lattice.getDeclNullability(DRE->getDecl());
Sam McCall7d9afee2023-06-27 01:43:24 -0700277 if (const auto *ME = dyn_cast<MemberExpr>(E))
Sam McCall74bf8642023-06-16 11:21:42 -0700278 return Lattice.getDeclNullability(ME->getMemberDecl());
279 return nullptr;
280}
281
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800282void transferFlowSensitivePointer(
Sam McCall7d9afee2023-06-27 01:43:24 -0700283 const Expr *PointerExpr, const MatchFinder::MatchResult &Result,
284 TransferState<PointerNullabilityLattice> &State) {
285 auto &Env = State.Env;
286 if (auto *PointerVal = getPointerValueFromExpr(PointerExpr, Env)) {
287 if (auto *Override = getOverriddenNullability(PointerExpr, State.Lattice)) {
Sam McCall74bf8642023-06-16 11:21:42 -0700288 // is_known = (nonnull | nullable)
289 initPointerNullState(
290 *PointerVal, Env,
291 &Env.makeOr(*Override->Nonnull, *Override->Nullable));
292 // nonnull => !is_null
293 auto [IsKnown, IsNull] = getPointerNullState(*PointerVal);
294 Env.addToFlowCondition(
295 Env.makeImplication(*Override->Nonnull, Env.makeNot(IsNull)));
296 } else {
297 initPointerFromAnnotations(*PointerVal, PointerExpr, State);
298 }
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700299 }
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700300}
301
Wei Yi Tee8b58e192022-08-02 10:15:40 -0700302// TODO(b/233582219): Implement promotion of nullability knownness for initially
303// unknown pointers when there is evidence that it is nullable, for example
304// when the pointer is compared to nullptr, or casted to boolean.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800305void transferFlowSensitiveNullCheckComparison(
Sam McCall7d9afee2023-06-27 01:43:24 -0700306 const BinaryOperator *BinaryOp, const MatchFinder::MatchResult &result,
307 TransferState<PointerNullabilityLattice> &State) {
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700308 // Boolean representing the comparison between the two pointer values,
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800309 // automatically created by the dataflow framework.
Sam McCall7d9afee2023-06-27 01:43:24 -0700310 auto &PointerComparison =
Martin Brænne0da58852023-05-23 06:43:57 -0700311 *cast<BoolValue>(State.Env.getValueStrict(*BinaryOp));
Wei Yi Tee543af742022-06-01 06:52:24 -0700312
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700313 CHECK(BinaryOp->getOpcode() == BO_EQ || BinaryOp->getOpcode() == BO_NE);
Sam McCall7d9afee2023-06-27 01:43:24 -0700314 auto &PointerEQ = BinaryOp->getOpcode() == BO_EQ
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700315 ? PointerComparison
316 : State.Env.makeNot(PointerComparison);
Sam McCall7d9afee2023-06-27 01:43:24 -0700317 auto &PointerNE = BinaryOp->getOpcode() == BO_EQ
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700318 ? State.Env.makeNot(PointerComparison)
319 : PointerComparison;
320
Sam McCall7d9afee2023-06-27 01:43:24 -0700321 auto *LHS = getPointerValueFromExpr(BinaryOp->getLHS(), State.Env);
322 auto *RHS = getPointerValueFromExpr(BinaryOp->getRHS(), State.Env);
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700323
324 if (!LHS || !RHS) return;
325
Sam McCall7d9afee2023-06-27 01:43:24 -0700326 auto &LHSNull = getPointerNullState(*LHS).second;
327 auto &RHSNull = getPointerNullState(*RHS).second;
328 auto &LHSNotNull = State.Env.makeNot(LHSNull);
329 auto &RHSNotNull = State.Env.makeNot(RHSNull);
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700330
Wei Yi Tee06f06962022-08-02 09:49:50 -0700331 // nullptr == nullptr
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700332 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700333 State.Env.makeAnd(LHSNull, RHSNull), PointerEQ));
Wei Yi Tee06f06962022-08-02 09:49:50 -0700334 // nullptr != notnull
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700335 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700336 State.Env.makeAnd(LHSNull, RHSNotNull), PointerNE));
Wei Yi Tee06f06962022-08-02 09:49:50 -0700337 // notnull != nullptr
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700338 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700339 State.Env.makeAnd(LHSNotNull, RHSNull), PointerNE));
Wei Yi Tee543af742022-06-01 06:52:24 -0700340}
341
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800342void transferFlowSensitiveNullCheckImplicitCastPtrToBool(
Sam McCall7d9afee2023-06-27 01:43:24 -0700343 const Expr *CastExpr, const MatchFinder::MatchResult &,
344 TransferState<PointerNullabilityLattice> &State) {
345 auto *PointerVal =
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700346 getPointerValueFromExpr(CastExpr->IgnoreImplicit(), State.Env);
347 if (!PointerVal) return;
348
Googlerf164e032023-05-18 08:38:51 -0700349 auto [PointerKnown, PointerNull] = getPointerNullState(*PointerVal);
Martin Brænne0da58852023-05-23 06:43:57 -0700350 State.Env.setValueStrict(*CastExpr, State.Env.makeNot(PointerNull));
Wei Yi Tee543af742022-06-01 06:52:24 -0700351}
352
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800353void transferFlowSensitiveCallExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700354 const CallExpr *CallExpr, const MatchFinder::MatchResult &Result,
355 TransferState<PointerNullabilityLattice> &State) {
Martin Brænnec307b1f2023-04-20 07:16:35 -0700356 // The dataflow framework itself does not create values for `CallExpr`s.
357 // However, we need these in some cases, so we produce them ourselves.
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700358
Sam McCall7d9afee2023-06-27 01:43:24 -0700359 dataflow::StorageLocation *Loc = nullptr;
Martin Brænne0da58852023-05-23 06:43:57 -0700360 if (CallExpr->isGLValue()) {
361 // The function returned a reference. Create a storage location for the
362 // expression so that if code creates a pointer from the reference, we will
363 // produce a `PointerValue`.
364 Loc = State.Env.getStorageLocationStrict(*CallExpr);
365 if (!Loc) {
366 // This is subtle: We call `createStorageLocation(QualType)`, not
367 // `createStorageLocation(const Expr &)`, so that we create a new
368 // storage location every time.
369 Loc = &State.Env.createStorageLocation(CallExpr->getType());
370 State.Env.setStorageLocationStrict(*CallExpr, *Loc);
371 }
372 }
373
Martin Brænnec307b1f2023-04-20 07:16:35 -0700374 if (CallExpr->getType()->isAnyPointerType()) {
375 // Create a pointer so that we can attach nullability to it and have the
376 // nullability propagate with the pointer.
Sam McCall7d9afee2023-06-27 01:43:24 -0700377 auto *PointerVal = getPointerValueFromExpr(CallExpr, State.Env);
Martin Brænnec307b1f2023-04-20 07:16:35 -0700378 if (!PointerVal) {
379 PointerVal =
380 cast<PointerValue>(State.Env.createValue(CallExpr->getType()));
Martin Brænnec307b1f2023-04-20 07:16:35 -0700381 }
382 initPointerFromAnnotations(*PointerVal, CallExpr, State);
Martin Brænne0da58852023-05-23 06:43:57 -0700383
384 if (Loc != nullptr)
385 State.Env.setValue(*Loc, *PointerVal);
386 else
387 // `Loc` is set iff `CallExpr` is a glvalue, so we know here that it must
388 // be a prvalue.
389 State.Env.setValueStrict(*CallExpr, *PointerVal);
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700390 }
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700391}
392
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800393void transferNonFlowSensitiveDeclRefExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700394 const DeclRefExpr *DRE, const MatchFinder::MatchResult &MR,
395 TransferState<PointerNullabilityLattice> &State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800396 computeNullability(DRE, State, [&] {
397 return getNullabilityAnnotationsFromType(DRE->getType());
398 });
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800399}
400
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800401void transferNonFlowSensitiveMemberExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700402 const MemberExpr *ME, const MatchFinder::MatchResult &MR,
403 TransferState<PointerNullabilityLattice> &State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800404 computeNullability(ME, State, [&]() {
Googlerd4437312023-01-17 15:10:29 -0800405 auto BaseNullability = getNullabilityForChild(ME->getBase(), State);
406 QualType MemberType = ME->getType();
407 // When a MemberExpr is a part of a member function call
408 // (a child of CXXMemberCallExpr), the MemberExpr models a
409 // partially-applied member function, which isn't a real C++ construct.
410 // The AST does not provide rich type information for such MemberExprs.
411 // Instead, the AST specifies a placeholder type, specifically
412 // BuiltinType::BoundMember. So we have to look at the type of the member
413 // function declaration.
414 if (ME->hasPlaceholderType(BuiltinType::BoundMember)) {
415 MemberType = ME->getMemberDecl()->getType();
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800416 }
Googlerd4437312023-01-17 15:10:29 -0800417 return substituteNullabilityAnnotationsInClassTemplate(
418 MemberType, BaseNullability, ME->getBase()->getType());
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800419 });
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800420}
421
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800422void transferNonFlowSensitiveMemberCallExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700423 const CXXMemberCallExpr *MCE, const MatchFinder::MatchResult &MR,
424 TransferState<PointerNullabilityLattice> &State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800425 computeNullability(MCE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700426 return ArrayRef(getNullabilityForChild(MCE->getCallee(), State))
Martin Brænnec4903062023-04-24 23:40:36 -0700427 .take_front(countPointersInType(MCE))
428 .vec();
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800429 });
430}
431
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800432void transferNonFlowSensitiveCastExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700433 const CastExpr *CE, const MatchFinder::MatchResult &MR,
434 TransferState<PointerNullabilityLattice> &State) {
Sam McCalld127f932023-05-02 07:15:27 -0700435 computeNullability(CE, State, [&]() -> TypeNullability {
Sam McCall2245db22023-04-17 06:50:25 -0700436 // Most casts that can convert ~unrelated types drop nullability in general.
437 // As a special case, preserve nullability of outer pointer types.
438 // For example, int* p; (void*)p; is a BitCast, but preserves nullability.
Sam McCalld127f932023-05-02 07:15:27 -0700439 auto PreserveTopLevelPointers = [&](TypeNullability V) {
Sam McCall2245db22023-04-17 06:50:25 -0700440 auto ArgNullability = getNullabilityForChild(CE->getSubExpr(), State);
Sam McCall7d9afee2023-06-27 01:43:24 -0700441 const PointerType *ArgType = dyn_cast<PointerType>(
Sam McCall2245db22023-04-17 06:50:25 -0700442 CE->getSubExpr()->getType().getCanonicalType().getTypePtr());
Sam McCall7d9afee2023-06-27 01:43:24 -0700443 const PointerType *CastType =
Sam McCall2245db22023-04-17 06:50:25 -0700444 dyn_cast<PointerType>(CE->getType().getCanonicalType().getTypePtr());
445 for (int I = 0; ArgType && CastType; ++I) {
446 V[I] = ArgNullability[I];
447 ArgType = dyn_cast<PointerType>(ArgType->getPointeeType().getTypePtr());
448 CastType =
449 dyn_cast<PointerType>(CastType->getPointeeType().getTypePtr());
450 }
451 return V;
452 };
453
454 switch (CE->getCastKind()) {
455 // Casts between unrelated types: we can't say anything about nullability.
456 case CK_LValueBitCast:
457 case CK_BitCast:
458 case CK_LValueToRValueBitCast:
459 return PreserveTopLevelPointers(unspecifiedNullability(CE));
460
461 // Casts between equivalent types.
462 case CK_LValueToRValue:
463 case CK_NoOp:
464 case CK_AtomicToNonAtomic:
465 case CK_NonAtomicToAtomic:
466 case CK_AddressSpaceConversion:
Sam McCalld127f932023-05-02 07:15:27 -0700467 return getNullabilityForChild(CE->getSubExpr(), State);
Sam McCall2245db22023-04-17 06:50:25 -0700468
469 // Controlled conversions between types
470 // TODO: these should be doable somehow
471 case CK_BaseToDerived:
472 case CK_DerivedToBase:
473 case CK_UncheckedDerivedToBase:
474 return PreserveTopLevelPointers(unspecifiedNullability(CE));
475 case CK_UserDefinedConversion:
476 case CK_ConstructorConversion:
477 return unspecifiedNullability(CE);
478
479 case CK_Dynamic: {
480 auto Result = unspecifiedNullability(CE);
481 // A dynamic_cast to pointer is null if the runtime check fails.
482 if (isa<PointerType>(CE->getType().getCanonicalType()))
483 Result.front() = NullabilityKind::Nullable;
484 return Result;
485 }
486
487 // Primitive values have no nullability.
488 case CK_ToVoid:
489 case CK_MemberPointerToBoolean:
490 case CK_PointerToBoolean:
491 case CK_PointerToIntegral:
492 case CK_IntegralCast:
493 case CK_IntegralToBoolean:
494 case CK_IntegralToFloating:
495 case CK_FloatingToFixedPoint:
496 case CK_FixedPointToFloating:
497 case CK_FixedPointCast:
498 case CK_FixedPointToIntegral:
499 case CK_IntegralToFixedPoint:
500 case CK_FixedPointToBoolean:
501 case CK_FloatingToIntegral:
502 case CK_FloatingToBoolean:
503 case CK_BooleanToSignedIntegral:
504 case CK_FloatingCast:
505 case CK_FloatingRealToComplex:
506 case CK_FloatingComplexToReal:
507 case CK_FloatingComplexToBoolean:
508 case CK_FloatingComplexCast:
509 case CK_FloatingComplexToIntegralComplex:
510 case CK_IntegralRealToComplex:
511 case CK_IntegralComplexToReal:
512 case CK_IntegralComplexToBoolean:
513 case CK_IntegralComplexCast:
514 case CK_IntegralComplexToFloatingComplex:
515 return {};
516
517 // This can definitely be null!
518 case CK_NullToPointer: {
519 auto Nullability = getNullabilityAnnotationsFromType(CE->getType());
Martin Brænne60e4c362023-06-21 02:44:41 -0700520 // Despite the name `NullToPointer`, the destination type of the cast
521 // may be `nullptr_t` (which is, itself, not a pointer type).
522 if (!CE->getType()->isNullPtrType())
523 Nullability.front() = NullabilityKind::Nullable;
Sam McCall2245db22023-04-17 06:50:25 -0700524 return Nullability;
525 }
526
527 // Pointers out of thin air, who knows?
528 case CK_IntegralToPointer:
529 return unspecifiedNullability(CE);
530
531 // Decayed objects are never null.
532 case CK_ArrayToPointerDecay:
533 case CK_FunctionToPointerDecay:
Sam McCall2245db22023-04-17 06:50:25 -0700534 return prepend(NullabilityKind::NonNull,
535 getNullabilityForChild(CE->getSubExpr(), State));
536
Martin Brænne381e2b92023-06-26 01:02:48 -0700537 // Despite its name, the result type of `BuiltinFnToFnPtr` is a function,
538 // not a function pointer, so nullability doesn't change.
539 case CK_BuiltinFnToFnPtr:
540 return getNullabilityForChild(CE->getSubExpr(), State);
541
Sam McCall2245db22023-04-17 06:50:25 -0700542 // TODO: what is our model of member pointers?
543 case CK_BaseToDerivedMemberPointer:
544 case CK_DerivedToBaseMemberPointer:
545 case CK_NullToMemberPointer:
546 case CK_ReinterpretMemberPointer:
547 case CK_ToUnion: // and unions?
548 return unspecifiedNullability(CE);
549
550 // TODO: Non-C/C++ constructs, do we care about these?
551 case CK_CPointerToObjCPointerCast:
552 case CK_ObjCObjectLValueCast:
553 case CK_MatrixCast:
554 case CK_VectorSplat:
555 case CK_BlockPointerToObjCPointerCast:
556 case CK_AnyPointerToBlockPointerCast:
557 case CK_ARCProduceObject:
558 case CK_ARCConsumeObject:
559 case CK_ARCReclaimReturnedObject:
560 case CK_ARCExtendBlockObject:
561 case CK_CopyAndAutoreleaseBlockObject:
562 case CK_ZeroToOCLOpaqueType:
563 case CK_IntToOCLSampler:
564 return unspecifiedNullability(CE);
565
566 case CK_Dependent:
567 CHECK(false) << "Shouldn't see dependent casts here?";
568 }
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800569 });
570}
571
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800572void transferNonFlowSensitiveMaterializeTemporaryExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700573 const MaterializeTemporaryExpr *MTE, const MatchFinder::MatchResult &MR,
574 TransferState<PointerNullabilityLattice> &State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800575 computeNullability(MTE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700576 return getNullabilityForChild(MTE->getSubExpr(), State);
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800577 });
578}
579
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800580void transferNonFlowSensitiveCallExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700581 const CallExpr *CE, const MatchFinder::MatchResult &MR,
582 TransferState<PointerNullabilityLattice> &State) {
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800583 // TODO: Check CallExpr arguments in the diagnoser against the nullability of
584 // parameters.
Googler5ef1bdf2023-01-18 04:01:15 -0800585 computeNullability(CE, State, [&]() {
Martin Brænnec4903062023-04-24 23:40:36 -0700586 // TODO(mboehme): Instead of relying on Clang to propagate nullability sugar
587 // to the `CallExpr`'s type, we should extract nullability directly from the
588 // callee `Expr .
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800589 return substituteNullabilityAnnotationsInFunctionTemplate(CE->getType(),
590 CE);
591 });
592}
593
Googler2bccf742023-01-18 03:53:14 -0800594void transferNonFlowSensitiveUnaryOperator(
Sam McCall7d9afee2023-06-27 01:43:24 -0700595 const UnaryOperator *UO, const MatchFinder::MatchResult &MR,
596 TransferState<PointerNullabilityLattice> &State) {
Sam McCalld127f932023-05-02 07:15:27 -0700597 computeNullability(UO, State, [&]() -> TypeNullability {
Googler5ef1bdf2023-01-18 04:01:15 -0800598 switch (UO->getOpcode()) {
599 case UO_AddrOf:
600 return prepend(NullabilityKind::NonNull,
601 getNullabilityForChild(UO->getSubExpr(), State));
602 case UO_Deref:
Sam McCalld127f932023-05-02 07:15:27 -0700603 return ArrayRef(getNullabilityForChild(UO->getSubExpr(), State))
Googler5ef1bdf2023-01-18 04:01:15 -0800604 .drop_front()
605 .vec();
Googler2bccf742023-01-18 03:53:14 -0800606
Googler5ef1bdf2023-01-18 04:01:15 -0800607 case UO_PostInc:
608 case UO_PostDec:
609 case UO_PreInc:
610 case UO_PreDec:
611 case UO_Plus:
612 case UO_Minus:
613 case UO_Not:
614 case UO_LNot:
615 case UO_Real:
616 case UO_Imag:
617 case UO_Extension:
618 return getNullabilityForChild(UO->getSubExpr(), State);
Googler2bccf742023-01-18 03:53:14 -0800619
Googler5ef1bdf2023-01-18 04:01:15 -0800620 case UO_Coawait:
621 // TODO: work out what to do here!
622 return unspecifiedNullability(UO);
623 }
624 });
Googler2bccf742023-01-18 03:53:14 -0800625}
626
Martin Brænne66bc2432023-04-18 23:48:49 -0700627void transferNonFlowSensitiveNewExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700628 const CXXNewExpr *NE, const MatchFinder::MatchResult &MR,
629 TransferState<PointerNullabilityLattice> &State) {
Martin Brænne66bc2432023-04-18 23:48:49 -0700630 computeNullability(NE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700631 TypeNullability result = getNullabilityAnnotationsFromType(NE->getType());
Martin Brænne66bc2432023-04-18 23:48:49 -0700632 result.front() = NE->shouldNullCheckAllocation() ? NullabilityKind::Nullable
633 : NullabilityKind::NonNull;
634 return result;
635 });
636}
637
Sam McCallf2b62b32023-05-02 06:45:40 -0700638void transferNonFlowSensitiveArraySubscriptExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700639 const ArraySubscriptExpr *ASE, const MatchFinder::MatchResult &MR,
640 TransferState<PointerNullabilityLattice> &State) {
Sam McCallf2b62b32023-05-02 06:45:40 -0700641 computeNullability(ASE, State, [&]() {
Sam McCall7d9afee2023-06-27 01:43:24 -0700642 auto &BaseNullability = getNullabilityForChild(ASE->getBase(), State);
Sam McCallf2b62b32023-05-02 06:45:40 -0700643 CHECK(ASE->getBase()->getType()->isAnyPointerType());
Sam McCalld127f932023-05-02 07:15:27 -0700644 return ArrayRef(BaseNullability).slice(1).vec();
Sam McCallf2b62b32023-05-02 06:45:40 -0700645 });
646}
647
Martin Brænne834d4b82023-05-15 07:07:05 -0700648void transferNonFlowSensitiveThisExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700649 const CXXThisExpr *TE, const MatchFinder::MatchResult &MR,
650 TransferState<PointerNullabilityLattice> &State) {
Martin Brænne834d4b82023-05-15 07:07:05 -0700651 computeNullability(TE, State, [&]() {
652 TypeNullability result = getNullabilityAnnotationsFromType(TE->getType());
653 result.front() = NullabilityKind::NonNull;
654 return result;
655 });
656}
657
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800658auto buildNonFlowSensitiveTransferer() {
659 return CFGMatchSwitchBuilder<TransferState<PointerNullabilityLattice>>()
660 .CaseOfCFGStmt<DeclRefExpr>(ast_matchers::declRefExpr(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800661 transferNonFlowSensitiveDeclRefExpr)
662 .CaseOfCFGStmt<MemberExpr>(ast_matchers::memberExpr(),
663 transferNonFlowSensitiveMemberExpr)
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800664 .CaseOfCFGStmt<CXXMemberCallExpr>(ast_matchers::cxxMemberCallExpr(),
665 transferNonFlowSensitiveMemberCallExpr)
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800666 .CaseOfCFGStmt<CastExpr>(ast_matchers::castExpr(),
667 transferNonFlowSensitiveCastExpr)
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800668 .CaseOfCFGStmt<MaterializeTemporaryExpr>(
669 ast_matchers::materializeTemporaryExpr(),
670 transferNonFlowSensitiveMaterializeTemporaryExpr)
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800671 .CaseOfCFGStmt<CallExpr>(ast_matchers::callExpr(),
672 transferNonFlowSensitiveCallExpr)
Googler2bccf742023-01-18 03:53:14 -0800673 .CaseOfCFGStmt<UnaryOperator>(ast_matchers::unaryOperator(),
674 transferNonFlowSensitiveUnaryOperator)
Martin Brænne66bc2432023-04-18 23:48:49 -0700675 .CaseOfCFGStmt<CXXNewExpr>(ast_matchers::cxxNewExpr(),
676 transferNonFlowSensitiveNewExpr)
Sam McCallf2b62b32023-05-02 06:45:40 -0700677 .CaseOfCFGStmt<ArraySubscriptExpr>(
678 ast_matchers::arraySubscriptExpr(),
679 transferNonFlowSensitiveArraySubscriptExpr)
Martin Brænne834d4b82023-05-15 07:07:05 -0700680 .CaseOfCFGStmt<CXXThisExpr>(ast_matchers::cxxThisExpr(),
681 transferNonFlowSensitiveThisExpr)
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800682 .Build();
683}
684
685auto buildFlowSensitiveTransferer() {
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800686 return CFGMatchSwitchBuilder<TransferState<PointerNullabilityLattice>>()
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800687 // Handles initialization of the null states of pointers.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800688 .CaseOfCFGStmt<Expr>(isAddrOf(), transferFlowSensitiveNotNullPointer)
Martin Brænne834d4b82023-05-15 07:07:05 -0700689 // TODO(mboehme): I believe we should be able to move handling of null
690 // pointers to the non-flow-sensitive part of the analysis.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800691 .CaseOfCFGStmt<Expr>(isNullPointerLiteral(),
692 transferFlowSensitiveNullPointer)
693 .CaseOfCFGStmt<CallExpr>(isCallExpr(), transferFlowSensitiveCallExpr)
694 .CaseOfCFGStmt<Expr>(isPointerExpr(), transferFlowSensitivePointer)
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800695 // Handles comparison between 2 pointers.
Wei Yi Tee217eb5f2022-09-15 03:18:28 -0700696 .CaseOfCFGStmt<BinaryOperator>(isPointerCheckBinOp(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800697 transferFlowSensitiveNullCheckComparison)
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800698 // Handles checking of pointer as boolean.
Wei Yi Tee217eb5f2022-09-15 03:18:28 -0700699 .CaseOfCFGStmt<Expr>(isImplicitCastPointerToBool(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800700 transferFlowSensitiveNullCheckImplicitCastPtrToBool)
Wei Yi Tee543af742022-06-01 06:52:24 -0700701 .Build();
702}
703} // namespace
704
Sam McCall7d9afee2023-06-27 01:43:24 -0700705PointerNullabilityAnalysis::PointerNullabilityAnalysis(ASTContext &Context)
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800706 : DataflowAnalysis<PointerNullabilityAnalysis, PointerNullabilityLattice>(
707 Context),
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800708 NonFlowSensitiveTransferer(buildNonFlowSensitiveTransferer()),
709 FlowSensitiveTransferer(buildFlowSensitiveTransferer()) {}
Wei Yi Tee543af742022-06-01 06:52:24 -0700710
Sam McCall74bf8642023-06-16 11:21:42 -0700711PointerTypeNullability PointerNullabilityAnalysis::assignNullabilityVariable(
Sam McCall7d9afee2023-06-27 01:43:24 -0700712 const ValueDecl *D, dataflow::Arena &A) {
Sam McCall74bf8642023-06-16 11:21:42 -0700713 auto [It, Inserted] = NFS.DeclTopLevelNullability.try_emplace(D);
714 if (Inserted) {
715 It->second.Nonnull = &A.create<dataflow::AtomicBoolValue>();
716 It->second.Nullable = &A.create<dataflow::AtomicBoolValue>();
717 }
718 return It->second;
719}
720
Sam McCall7d9afee2023-06-27 01:43:24 -0700721void PointerNullabilityAnalysis::transfer(const CFGElement &Elt,
722 PointerNullabilityLattice &Lattice,
723 Environment &Env) {
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800724 TransferState<PointerNullabilityLattice> State(Lattice, Env);
Googler9949b462023-02-15 05:09:07 -0800725 NonFlowSensitiveTransferer(Elt, getASTContext(), State);
726 FlowSensitiveTransferer(Elt, getASTContext(), State);
Wei Yi Tee543af742022-06-01 06:52:24 -0700727}
728
Sam McCall7d9afee2023-06-27 01:43:24 -0700729BoolValue &mergeBoolValues(BoolValue &Bool1, const Environment &Env1,
730 BoolValue &Bool2, const Environment &Env2,
731 Environment &MergedEnv) {
Wei Yi Tee721ee972022-08-11 01:14:54 -0700732 if (&Bool1 == &Bool2) {
733 return Bool1;
734 }
735
Sam McCall7d9afee2023-06-27 01:43:24 -0700736 auto &MergedBool = MergedEnv.makeAtomicBoolValue();
Wei Yi Tee721ee972022-08-11 01:14:54 -0700737
738 // If `Bool1` and `Bool2` is constrained to the same true / false value,
739 // `MergedBool` can be constrained similarly without needing to consider the
740 // path taken - this simplifies the flow condition tracked in `MergedEnv`.
741 // Otherwise, information about which path was taken is used to associate
742 // `MergedBool` with `Bool1` and `Bool2`.
743 if (Env1.flowConditionImplies(Bool1) && Env2.flowConditionImplies(Bool2)) {
744 MergedEnv.addToFlowCondition(MergedBool);
745 } else if (Env1.flowConditionImplies(Env1.makeNot(Bool1)) &&
746 Env2.flowConditionImplies(Env2.makeNot(Bool2))) {
747 MergedEnv.addToFlowCondition(MergedEnv.makeNot(MergedBool));
748 } else {
749 // TODO(b/233582219): Flow conditions are not necessarily mutually
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800750 // exclusive, a fix is in order: https://reviews.llvm.org/D130270. Update
751 // this section when the patch is commited.
Sam McCall7d9afee2023-06-27 01:43:24 -0700752 auto &FC1 = Env1.getFlowConditionToken();
753 auto &FC2 = Env2.getFlowConditionToken();
Wei Yi Tee721ee972022-08-11 01:14:54 -0700754 MergedEnv.addToFlowCondition(MergedEnv.makeOr(
755 MergedEnv.makeAnd(FC1, MergedEnv.makeIff(MergedBool, Bool1)),
756 MergedEnv.makeAnd(FC2, MergedEnv.makeIff(MergedBool, Bool2))));
757 }
758 return MergedBool;
759}
760
Sam McCall7d9afee2023-06-27 01:43:24 -0700761bool PointerNullabilityAnalysis::merge(QualType Type, const Value &Val1,
762 const Environment &Env1,
763 const Value &Val2,
764 const Environment &Env2,
765 Value &MergedVal,
766 Environment &MergedEnv) {
Wei Yi Tee721ee972022-08-11 01:14:54 -0700767 if (!Type->isAnyPointerType()) {
768 return false;
769 }
770
Martin Brænneed01de62023-06-13 05:45:21 -0700771 if (!hasPointerNullState(cast<PointerValue>(Val1)) ||
772 !hasPointerNullState(cast<PointerValue>(Val2))) {
773 return false;
774 }
775
Googlerf164e032023-05-18 08:38:51 -0700776 auto [Known1, Null1] = getPointerNullState(cast<PointerValue>(Val1));
777 auto [Known2, Null2] = getPointerNullState(cast<PointerValue>(Val2));
Wei Yi Tee721ee972022-08-11 01:14:54 -0700778
Sam McCall7d9afee2023-06-27 01:43:24 -0700779 auto &Known = mergeBoolValues(Known1, Env1, Known2, Env2, MergedEnv);
780 auto &Null = mergeBoolValues(Null1, Env1, Null2, Env2, MergedEnv);
Wei Yi Tee721ee972022-08-11 01:14:54 -0700781
Dani Ferreira Franco Mouraa0649822022-11-11 07:55:05 -0800782 initPointerNullState(cast<PointerValue>(MergedVal), MergedEnv, &Known, &Null);
Wei Yi Tee721ee972022-08-11 01:14:54 -0700783
784 return true;
Wei Yi Tee543af742022-06-01 06:52:24 -0700785}
Sam McCall5fc2a802023-05-02 05:41:27 -0700786
Sam McCall4f6be422023-06-27 02:51:22 -0700787} // namespace clang::tidy::nullability