blob: d09b6a41dc2b53f88b89c156ddc4dda0a3e519ea [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
Martin Brænne9eca4f72023-06-29 21:42:23 -0700151 // TODO: If the type was substituted from a pack template argument,
152 // we must find the slice that pertains to this particular type.
153 // For now, just give up on resugaring this type.
154 if (ST->getPackIndex().has_value()) return std::nullopt;
155
Sam McCalla45d2602023-04-28 13:20:15 -0700156 unsigned PointerCount =
157 countPointersInType(Specialization->getDeclContext());
Sam McCall28ab01a2023-01-23 05:15:48 -0800158 for (auto TA : TemplateArgs.take_front(ArgIndex)) {
159 PointerCount += countPointersInType(TA);
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800160 }
Martin Brænne9eca4f72023-06-29 21:42:23 -0700161
Sam McCall28ab01a2023-01-23 05:15:48 -0800162 unsigned SliceSize = countPointersInType(TemplateArgs[ArgIndex]);
Sam McCalld127f932023-05-02 07:15:27 -0700163 return ArrayRef(BaseNullabilityAnnotations)
164 .slice(PointerCount, SliceSize)
165 .vec();
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800166 });
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800167}
168
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800169/// Compute nullability annotations of `T`, which might contain template type
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800170/// variable substitutions bound by the call `CE`.
171///
172/// Example:
173///
174/// \code
175/// template<typename F, typename S>
176/// std::pair<S, F> flip(std::pair<F, S> p);
177/// \endcode
178///
179/// Consider the following CallExpr:
180///
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800181/// \code
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800182/// flip<int * _Nonnull, int * _Nullable>(std::make_pair(&x, &y));
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800183/// \endcode
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800184///
185/// This CallExpr has the following substitutions:
186/// F=int * _Nonnull, whose nullability is [_Nonnull]
187/// S=int * _Nullable, whose nullability is [_Nullable]
188///
189/// The return type of this CallExpr is `std::pair<S, F>`.
190///
191/// When we call `substituteNullabilityAnnotationsInFunctionTemplate` with the
192/// type `std::pair<S, F>` and the above CallExpr, it returns the nullability
193/// the given type after applying substitutions, which in this case is
194/// [_Nullable, _Nonnull].
Sam McCalld127f932023-05-02 07:15:27 -0700195TypeNullability substituteNullabilityAnnotationsInFunctionTemplate(
Sam McCall7d9afee2023-06-27 01:43:24 -0700196 QualType T, const CallExpr *CE) {
Sam McCall932b7432023-01-23 04:41:22 -0800197 return getNullabilityAnnotationsFromType(
198 T,
Sam McCall7d9afee2023-06-27 01:43:24 -0700199 [&](const SubstTemplateTypeParmType *ST)
Sam McCalld127f932023-05-02 07:15:27 -0700200 -> std::optional<TypeNullability> {
lujin13729102023-07-03 15:25:25 +0000201 auto *DRE = dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreImpCasts());
202 if (DRE == nullptr) return std::nullopt;
203
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800204 // TODO: Handle calls that use template argument deduction.
lujin13729102023-07-03 15:25:25 +0000205
206 // Does this refer to a parameter of the function template?
207 // If not (e.g. nested templates, template specialization types in the
208 // return value), we handle the desugaring elsewhere.
209 auto *ReferencedFunction = dyn_cast<FunctionDecl>(DRE->getDecl());
210 if (!ReferencedFunction) return std::nullopt;
211 if (ReferencedFunction->getPrimaryTemplate() != ST->getAssociatedDecl())
212 return std::nullopt;
213
214 // Some or all of the template arguments may be deduced, and we won't
215 // see those on the `DeclRefExpr`. If the template argument was deduced,
216 // we don't have any sugar for it.
217 // TODO(b/268348533): Can we somehow obtain it from the function param
218 // it was deduced from?
219 // TODO(b/268345783): This check, as well as the index into
220 // `template_arguments` below, may be incorrect in the presence of
221 // parameters packs. In function templates, parameter packs may appear
222 // anywhere in the parameter list. The index may therefore refer to one
223 // of the pack arguments, but we might incorrectly interpret it as
224 // referring to an argument that follows the pack.
225 if (ST->getIndex() >= DRE->template_arguments().size())
226 return std::nullopt;
227
228 TypeSourceInfo *TSI =
229 DRE->template_arguments()[ST->getIndex()].getTypeSourceInfo();
230 if (TSI == nullptr) return std::nullopt;
231 return getNullabilityAnnotationsFromType(TSI->getType());
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800232 });
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -0800233}
234
Sam McCall7d9afee2023-06-27 01:43:24 -0700235NullabilityKind getPointerNullability(const Expr *E,
236 PointerNullabilityAnalysis::Lattice &L) {
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800237 QualType ExprType = E->getType();
Googlerbad70522023-01-31 04:37:38 -0800238 std::optional<NullabilityKind> Nullability = ExprType->getNullability();
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800239
240 // If the expression's type does not contain nullability information, it may
241 // be a template instantiation. Look up the nullability in the
242 // `ExprToNullability` map.
243 if (Nullability.value_or(NullabilityKind::Unspecified) ==
244 NullabilityKind::Unspecified) {
245 if (auto MaybeNullability = L.getExprNullability(E)) {
246 if (!MaybeNullability->empty()) {
247 // Return the nullability of the topmost pointer in the type.
248 Nullability = (*MaybeNullability)[0];
249 }
250 }
251 }
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800252 return Nullability.value_or(NullabilityKind::Unspecified);
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800253}
254
Dani Ferreira Franco Moura1d41c112022-12-21 08:43:32 -0800255void initPointerFromAnnotations(
Sam McCall7d9afee2023-06-27 01:43:24 -0700256 PointerValue &PointerVal, const Expr *E,
257 TransferState<PointerNullabilityLattice> &State) {
Dani Ferreira Franco Moura1d41c112022-12-21 08:43:32 -0800258 NullabilityKind Nullability = getPointerNullability(E, State.Lattice);
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700259 switch (Nullability) {
260 case NullabilityKind::NonNull:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800261 initNotNullPointer(PointerVal, State.Env);
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700262 break;
Wei Yi Teeae43f392022-08-02 11:33:23 -0700263 case NullabilityKind::Nullable:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800264 initNullablePointer(PointerVal, State.Env);
Wei Yi Teeae43f392022-08-02 11:33:23 -0700265 break;
266 default:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800267 initUnknownPointer(PointerVal, State.Env);
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700268 }
269}
270
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800271void transferFlowSensitiveNullPointer(
Sam McCall7d9afee2023-06-27 01:43:24 -0700272 const Expr *NullPointer, const MatchFinder::MatchResult &,
273 TransferState<PointerNullabilityLattice> &State) {
274 if (auto *PointerVal = getPointerValueFromExpr(NullPointer, State.Env)) {
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700275 initNullPointer(*PointerVal, State.Env);
276 }
277}
278
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800279void transferFlowSensitiveNotNullPointer(
Sam McCall7d9afee2023-06-27 01:43:24 -0700280 const Expr *NotNullPointer, const MatchFinder::MatchResult &,
281 TransferState<PointerNullabilityLattice> &State) {
282 if (auto *PointerVal = getPointerValueFromExpr(NotNullPointer, State.Env)) {
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700283 initNotNullPointer(*PointerVal, State.Env);
284 }
285}
286
Sam McCall7d9afee2023-06-27 01:43:24 -0700287const PointerTypeNullability *getOverriddenNullability(
288 const Expr *E, PointerNullabilityLattice &Lattice) {
289 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
Sam McCall74bf8642023-06-16 11:21:42 -0700290 return Lattice.getDeclNullability(DRE->getDecl());
Sam McCall7d9afee2023-06-27 01:43:24 -0700291 if (const auto *ME = dyn_cast<MemberExpr>(E))
Sam McCall74bf8642023-06-16 11:21:42 -0700292 return Lattice.getDeclNullability(ME->getMemberDecl());
293 return nullptr;
294}
295
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800296void transferFlowSensitivePointer(
Sam McCall7d9afee2023-06-27 01:43:24 -0700297 const Expr *PointerExpr, const MatchFinder::MatchResult &Result,
298 TransferState<PointerNullabilityLattice> &State) {
299 auto &Env = State.Env;
300 if (auto *PointerVal = getPointerValueFromExpr(PointerExpr, Env)) {
301 if (auto *Override = getOverriddenNullability(PointerExpr, State.Lattice)) {
Sam McCall74bf8642023-06-16 11:21:42 -0700302 // is_known = (nonnull | nullable)
303 initPointerNullState(
304 *PointerVal, Env,
305 &Env.makeOr(*Override->Nonnull, *Override->Nullable));
306 // nonnull => !is_null
307 auto [IsKnown, IsNull] = getPointerNullState(*PointerVal);
308 Env.addToFlowCondition(
309 Env.makeImplication(*Override->Nonnull, Env.makeNot(IsNull)));
310 } else {
311 initPointerFromAnnotations(*PointerVal, PointerExpr, State);
312 }
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700313 }
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700314}
315
Wei Yi Tee8b58e192022-08-02 10:15:40 -0700316// TODO(b/233582219): Implement promotion of nullability knownness for initially
317// unknown pointers when there is evidence that it is nullable, for example
318// when the pointer is compared to nullptr, or casted to boolean.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800319void transferFlowSensitiveNullCheckComparison(
Sam McCall7d9afee2023-06-27 01:43:24 -0700320 const BinaryOperator *BinaryOp, const MatchFinder::MatchResult &result,
321 TransferState<PointerNullabilityLattice> &State) {
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700322 // Boolean representing the comparison between the two pointer values,
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800323 // automatically created by the dataflow framework.
Sam McCall7d9afee2023-06-27 01:43:24 -0700324 auto &PointerComparison =
Martin Brænne0da58852023-05-23 06:43:57 -0700325 *cast<BoolValue>(State.Env.getValueStrict(*BinaryOp));
Wei Yi Tee543af742022-06-01 06:52:24 -0700326
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700327 CHECK(BinaryOp->getOpcode() == BO_EQ || BinaryOp->getOpcode() == BO_NE);
Sam McCall7d9afee2023-06-27 01:43:24 -0700328 auto &PointerEQ = BinaryOp->getOpcode() == BO_EQ
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700329 ? PointerComparison
330 : State.Env.makeNot(PointerComparison);
Sam McCall7d9afee2023-06-27 01:43:24 -0700331 auto &PointerNE = BinaryOp->getOpcode() == BO_EQ
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700332 ? State.Env.makeNot(PointerComparison)
333 : PointerComparison;
334
Sam McCall7d9afee2023-06-27 01:43:24 -0700335 auto *LHS = getPointerValueFromExpr(BinaryOp->getLHS(), State.Env);
336 auto *RHS = getPointerValueFromExpr(BinaryOp->getRHS(), State.Env);
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700337
338 if (!LHS || !RHS) return;
339
Sam McCall7d9afee2023-06-27 01:43:24 -0700340 auto &LHSNull = getPointerNullState(*LHS).second;
341 auto &RHSNull = getPointerNullState(*RHS).second;
342 auto &LHSNotNull = State.Env.makeNot(LHSNull);
343 auto &RHSNotNull = State.Env.makeNot(RHSNull);
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700344
Wei Yi Tee06f06962022-08-02 09:49:50 -0700345 // nullptr == nullptr
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700346 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700347 State.Env.makeAnd(LHSNull, RHSNull), PointerEQ));
Wei Yi Tee06f06962022-08-02 09:49:50 -0700348 // nullptr != notnull
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700349 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700350 State.Env.makeAnd(LHSNull, RHSNotNull), PointerNE));
Wei Yi Tee06f06962022-08-02 09:49:50 -0700351 // notnull != nullptr
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700352 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700353 State.Env.makeAnd(LHSNotNull, RHSNull), PointerNE));
Wei Yi Tee543af742022-06-01 06:52:24 -0700354}
355
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800356void transferFlowSensitiveNullCheckImplicitCastPtrToBool(
Sam McCall7d9afee2023-06-27 01:43:24 -0700357 const Expr *CastExpr, const MatchFinder::MatchResult &,
358 TransferState<PointerNullabilityLattice> &State) {
359 auto *PointerVal =
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700360 getPointerValueFromExpr(CastExpr->IgnoreImplicit(), State.Env);
361 if (!PointerVal) return;
362
Googlerf164e032023-05-18 08:38:51 -0700363 auto [PointerKnown, PointerNull] = getPointerNullState(*PointerVal);
Martin Brænne0da58852023-05-23 06:43:57 -0700364 State.Env.setValueStrict(*CastExpr, State.Env.makeNot(PointerNull));
Wei Yi Tee543af742022-06-01 06:52:24 -0700365}
366
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800367void transferFlowSensitiveCallExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700368 const CallExpr *CallExpr, const MatchFinder::MatchResult &Result,
369 TransferState<PointerNullabilityLattice> &State) {
Martin Brænnec307b1f2023-04-20 07:16:35 -0700370 // The dataflow framework itself does not create values for `CallExpr`s.
371 // However, we need these in some cases, so we produce them ourselves.
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700372
Sam McCall7d9afee2023-06-27 01:43:24 -0700373 dataflow::StorageLocation *Loc = nullptr;
Martin Brænne0da58852023-05-23 06:43:57 -0700374 if (CallExpr->isGLValue()) {
375 // The function returned a reference. Create a storage location for the
376 // expression so that if code creates a pointer from the reference, we will
377 // produce a `PointerValue`.
378 Loc = State.Env.getStorageLocationStrict(*CallExpr);
379 if (!Loc) {
380 // This is subtle: We call `createStorageLocation(QualType)`, not
381 // `createStorageLocation(const Expr &)`, so that we create a new
382 // storage location every time.
383 Loc = &State.Env.createStorageLocation(CallExpr->getType());
384 State.Env.setStorageLocationStrict(*CallExpr, *Loc);
385 }
386 }
387
Martin Brænnec307b1f2023-04-20 07:16:35 -0700388 if (CallExpr->getType()->isAnyPointerType()) {
389 // Create a pointer so that we can attach nullability to it and have the
390 // nullability propagate with the pointer.
Sam McCall7d9afee2023-06-27 01:43:24 -0700391 auto *PointerVal = getPointerValueFromExpr(CallExpr, State.Env);
Martin Brænnec307b1f2023-04-20 07:16:35 -0700392 if (!PointerVal) {
393 PointerVal =
394 cast<PointerValue>(State.Env.createValue(CallExpr->getType()));
Martin Brænnec307b1f2023-04-20 07:16:35 -0700395 }
396 initPointerFromAnnotations(*PointerVal, CallExpr, State);
Martin Brænne0da58852023-05-23 06:43:57 -0700397
398 if (Loc != nullptr)
399 State.Env.setValue(*Loc, *PointerVal);
400 else
401 // `Loc` is set iff `CallExpr` is a glvalue, so we know here that it must
402 // be a prvalue.
403 State.Env.setValueStrict(*CallExpr, *PointerVal);
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700404 }
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700405}
406
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800407void transferNonFlowSensitiveDeclRefExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700408 const DeclRefExpr *DRE, const MatchFinder::MatchResult &MR,
409 TransferState<PointerNullabilityLattice> &State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800410 computeNullability(DRE, State, [&] {
411 return getNullabilityAnnotationsFromType(DRE->getType());
412 });
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800413}
414
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800415void transferNonFlowSensitiveMemberExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700416 const MemberExpr *ME, const MatchFinder::MatchResult &MR,
417 TransferState<PointerNullabilityLattice> &State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800418 computeNullability(ME, State, [&]() {
Googlerd4437312023-01-17 15:10:29 -0800419 auto BaseNullability = getNullabilityForChild(ME->getBase(), State);
420 QualType MemberType = ME->getType();
421 // When a MemberExpr is a part of a member function call
422 // (a child of CXXMemberCallExpr), the MemberExpr models a
423 // partially-applied member function, which isn't a real C++ construct.
424 // The AST does not provide rich type information for such MemberExprs.
425 // Instead, the AST specifies a placeholder type, specifically
426 // BuiltinType::BoundMember. So we have to look at the type of the member
427 // function declaration.
428 if (ME->hasPlaceholderType(BuiltinType::BoundMember)) {
429 MemberType = ME->getMemberDecl()->getType();
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800430 }
Googlerd4437312023-01-17 15:10:29 -0800431 return substituteNullabilityAnnotationsInClassTemplate(
432 MemberType, BaseNullability, ME->getBase()->getType());
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800433 });
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800434}
435
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800436void transferNonFlowSensitiveMemberCallExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700437 const CXXMemberCallExpr *MCE, const MatchFinder::MatchResult &MR,
438 TransferState<PointerNullabilityLattice> &State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800439 computeNullability(MCE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700440 return ArrayRef(getNullabilityForChild(MCE->getCallee(), State))
Martin Brænnec4903062023-04-24 23:40:36 -0700441 .take_front(countPointersInType(MCE))
442 .vec();
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800443 });
444}
445
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800446void transferNonFlowSensitiveCastExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700447 const CastExpr *CE, const MatchFinder::MatchResult &MR,
448 TransferState<PointerNullabilityLattice> &State) {
Sam McCalld127f932023-05-02 07:15:27 -0700449 computeNullability(CE, State, [&]() -> TypeNullability {
Sam McCall2245db22023-04-17 06:50:25 -0700450 // Most casts that can convert ~unrelated types drop nullability in general.
451 // As a special case, preserve nullability of outer pointer types.
452 // For example, int* p; (void*)p; is a BitCast, but preserves nullability.
Sam McCalld127f932023-05-02 07:15:27 -0700453 auto PreserveTopLevelPointers = [&](TypeNullability V) {
Sam McCall2245db22023-04-17 06:50:25 -0700454 auto ArgNullability = getNullabilityForChild(CE->getSubExpr(), State);
Sam McCall7d9afee2023-06-27 01:43:24 -0700455 const PointerType *ArgType = dyn_cast<PointerType>(
Sam McCall2245db22023-04-17 06:50:25 -0700456 CE->getSubExpr()->getType().getCanonicalType().getTypePtr());
Sam McCall7d9afee2023-06-27 01:43:24 -0700457 const PointerType *CastType =
Sam McCall2245db22023-04-17 06:50:25 -0700458 dyn_cast<PointerType>(CE->getType().getCanonicalType().getTypePtr());
459 for (int I = 0; ArgType && CastType; ++I) {
460 V[I] = ArgNullability[I];
461 ArgType = dyn_cast<PointerType>(ArgType->getPointeeType().getTypePtr());
462 CastType =
463 dyn_cast<PointerType>(CastType->getPointeeType().getTypePtr());
464 }
465 return V;
466 };
467
468 switch (CE->getCastKind()) {
469 // Casts between unrelated types: we can't say anything about nullability.
470 case CK_LValueBitCast:
471 case CK_BitCast:
472 case CK_LValueToRValueBitCast:
473 return PreserveTopLevelPointers(unspecifiedNullability(CE));
474
475 // Casts between equivalent types.
476 case CK_LValueToRValue:
477 case CK_NoOp:
478 case CK_AtomicToNonAtomic:
479 case CK_NonAtomicToAtomic:
480 case CK_AddressSpaceConversion:
Sam McCalld127f932023-05-02 07:15:27 -0700481 return getNullabilityForChild(CE->getSubExpr(), State);
Sam McCall2245db22023-04-17 06:50:25 -0700482
483 // Controlled conversions between types
484 // TODO: these should be doable somehow
485 case CK_BaseToDerived:
486 case CK_DerivedToBase:
487 case CK_UncheckedDerivedToBase:
488 return PreserveTopLevelPointers(unspecifiedNullability(CE));
489 case CK_UserDefinedConversion:
490 case CK_ConstructorConversion:
491 return unspecifiedNullability(CE);
492
493 case CK_Dynamic: {
494 auto Result = unspecifiedNullability(CE);
495 // A dynamic_cast to pointer is null if the runtime check fails.
496 if (isa<PointerType>(CE->getType().getCanonicalType()))
497 Result.front() = NullabilityKind::Nullable;
498 return Result;
499 }
500
501 // Primitive values have no nullability.
502 case CK_ToVoid:
503 case CK_MemberPointerToBoolean:
504 case CK_PointerToBoolean:
505 case CK_PointerToIntegral:
506 case CK_IntegralCast:
507 case CK_IntegralToBoolean:
508 case CK_IntegralToFloating:
509 case CK_FloatingToFixedPoint:
510 case CK_FixedPointToFloating:
511 case CK_FixedPointCast:
512 case CK_FixedPointToIntegral:
513 case CK_IntegralToFixedPoint:
514 case CK_FixedPointToBoolean:
515 case CK_FloatingToIntegral:
516 case CK_FloatingToBoolean:
517 case CK_BooleanToSignedIntegral:
518 case CK_FloatingCast:
519 case CK_FloatingRealToComplex:
520 case CK_FloatingComplexToReal:
521 case CK_FloatingComplexToBoolean:
522 case CK_FloatingComplexCast:
523 case CK_FloatingComplexToIntegralComplex:
524 case CK_IntegralRealToComplex:
525 case CK_IntegralComplexToReal:
526 case CK_IntegralComplexToBoolean:
527 case CK_IntegralComplexCast:
528 case CK_IntegralComplexToFloatingComplex:
529 return {};
530
531 // This can definitely be null!
532 case CK_NullToPointer: {
533 auto Nullability = getNullabilityAnnotationsFromType(CE->getType());
Martin Brænne60e4c362023-06-21 02:44:41 -0700534 // Despite the name `NullToPointer`, the destination type of the cast
535 // may be `nullptr_t` (which is, itself, not a pointer type).
536 if (!CE->getType()->isNullPtrType())
537 Nullability.front() = NullabilityKind::Nullable;
Sam McCall2245db22023-04-17 06:50:25 -0700538 return Nullability;
539 }
540
541 // Pointers out of thin air, who knows?
542 case CK_IntegralToPointer:
543 return unspecifiedNullability(CE);
544
545 // Decayed objects are never null.
546 case CK_ArrayToPointerDecay:
547 case CK_FunctionToPointerDecay:
Sam McCall2245db22023-04-17 06:50:25 -0700548 return prepend(NullabilityKind::NonNull,
549 getNullabilityForChild(CE->getSubExpr(), State));
550
Martin Brænne381e2b92023-06-26 01:02:48 -0700551 // Despite its name, the result type of `BuiltinFnToFnPtr` is a function,
552 // not a function pointer, so nullability doesn't change.
553 case CK_BuiltinFnToFnPtr:
554 return getNullabilityForChild(CE->getSubExpr(), State);
555
Sam McCall2245db22023-04-17 06:50:25 -0700556 // TODO: what is our model of member pointers?
557 case CK_BaseToDerivedMemberPointer:
558 case CK_DerivedToBaseMemberPointer:
559 case CK_NullToMemberPointer:
560 case CK_ReinterpretMemberPointer:
561 case CK_ToUnion: // and unions?
562 return unspecifiedNullability(CE);
563
564 // TODO: Non-C/C++ constructs, do we care about these?
565 case CK_CPointerToObjCPointerCast:
566 case CK_ObjCObjectLValueCast:
567 case CK_MatrixCast:
568 case CK_VectorSplat:
569 case CK_BlockPointerToObjCPointerCast:
570 case CK_AnyPointerToBlockPointerCast:
571 case CK_ARCProduceObject:
572 case CK_ARCConsumeObject:
573 case CK_ARCReclaimReturnedObject:
574 case CK_ARCExtendBlockObject:
575 case CK_CopyAndAutoreleaseBlockObject:
576 case CK_ZeroToOCLOpaqueType:
577 case CK_IntToOCLSampler:
578 return unspecifiedNullability(CE);
579
580 case CK_Dependent:
581 CHECK(false) << "Shouldn't see dependent casts here?";
582 }
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800583 });
584}
585
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800586void transferNonFlowSensitiveMaterializeTemporaryExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700587 const MaterializeTemporaryExpr *MTE, const MatchFinder::MatchResult &MR,
588 TransferState<PointerNullabilityLattice> &State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800589 computeNullability(MTE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700590 return getNullabilityForChild(MTE->getSubExpr(), State);
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800591 });
592}
593
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800594void transferNonFlowSensitiveCallExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700595 const CallExpr *CE, const MatchFinder::MatchResult &MR,
596 TransferState<PointerNullabilityLattice> &State) {
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800597 // TODO: Check CallExpr arguments in the diagnoser against the nullability of
598 // parameters.
Googler5ef1bdf2023-01-18 04:01:15 -0800599 computeNullability(CE, State, [&]() {
Martin Brænnec4903062023-04-24 23:40:36 -0700600 // TODO(mboehme): Instead of relying on Clang to propagate nullability sugar
601 // to the `CallExpr`'s type, we should extract nullability directly from the
602 // callee `Expr .
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800603 return substituteNullabilityAnnotationsInFunctionTemplate(CE->getType(),
604 CE);
605 });
606}
607
Googler2bccf742023-01-18 03:53:14 -0800608void transferNonFlowSensitiveUnaryOperator(
Sam McCall7d9afee2023-06-27 01:43:24 -0700609 const UnaryOperator *UO, const MatchFinder::MatchResult &MR,
610 TransferState<PointerNullabilityLattice> &State) {
Sam McCalld127f932023-05-02 07:15:27 -0700611 computeNullability(UO, State, [&]() -> TypeNullability {
Googler5ef1bdf2023-01-18 04:01:15 -0800612 switch (UO->getOpcode()) {
613 case UO_AddrOf:
614 return prepend(NullabilityKind::NonNull,
615 getNullabilityForChild(UO->getSubExpr(), State));
616 case UO_Deref:
Sam McCalld127f932023-05-02 07:15:27 -0700617 return ArrayRef(getNullabilityForChild(UO->getSubExpr(), State))
Googler5ef1bdf2023-01-18 04:01:15 -0800618 .drop_front()
619 .vec();
Googler2bccf742023-01-18 03:53:14 -0800620
Googler5ef1bdf2023-01-18 04:01:15 -0800621 case UO_PostInc:
622 case UO_PostDec:
623 case UO_PreInc:
624 case UO_PreDec:
625 case UO_Plus:
626 case UO_Minus:
627 case UO_Not:
628 case UO_LNot:
629 case UO_Real:
630 case UO_Imag:
631 case UO_Extension:
632 return getNullabilityForChild(UO->getSubExpr(), State);
Googler2bccf742023-01-18 03:53:14 -0800633
Googler5ef1bdf2023-01-18 04:01:15 -0800634 case UO_Coawait:
635 // TODO: work out what to do here!
636 return unspecifiedNullability(UO);
637 }
638 });
Googler2bccf742023-01-18 03:53:14 -0800639}
640
Martin Brænne66bc2432023-04-18 23:48:49 -0700641void transferNonFlowSensitiveNewExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700642 const CXXNewExpr *NE, const MatchFinder::MatchResult &MR,
643 TransferState<PointerNullabilityLattice> &State) {
Martin Brænne66bc2432023-04-18 23:48:49 -0700644 computeNullability(NE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700645 TypeNullability result = getNullabilityAnnotationsFromType(NE->getType());
Martin Brænne66bc2432023-04-18 23:48:49 -0700646 result.front() = NE->shouldNullCheckAllocation() ? NullabilityKind::Nullable
647 : NullabilityKind::NonNull;
648 return result;
649 });
650}
651
Sam McCallf2b62b32023-05-02 06:45:40 -0700652void transferNonFlowSensitiveArraySubscriptExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700653 const ArraySubscriptExpr *ASE, const MatchFinder::MatchResult &MR,
654 TransferState<PointerNullabilityLattice> &State) {
Sam McCallf2b62b32023-05-02 06:45:40 -0700655 computeNullability(ASE, State, [&]() {
Sam McCall7d9afee2023-06-27 01:43:24 -0700656 auto &BaseNullability = getNullabilityForChild(ASE->getBase(), State);
Sam McCallf2b62b32023-05-02 06:45:40 -0700657 CHECK(ASE->getBase()->getType()->isAnyPointerType());
Sam McCalld127f932023-05-02 07:15:27 -0700658 return ArrayRef(BaseNullability).slice(1).vec();
Sam McCallf2b62b32023-05-02 06:45:40 -0700659 });
660}
661
Martin Brænne834d4b82023-05-15 07:07:05 -0700662void transferNonFlowSensitiveThisExpr(
Sam McCall7d9afee2023-06-27 01:43:24 -0700663 const CXXThisExpr *TE, const MatchFinder::MatchResult &MR,
664 TransferState<PointerNullabilityLattice> &State) {
Martin Brænne834d4b82023-05-15 07:07:05 -0700665 computeNullability(TE, State, [&]() {
666 TypeNullability result = getNullabilityAnnotationsFromType(TE->getType());
667 result.front() = NullabilityKind::NonNull;
668 return result;
669 });
670}
671
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800672auto buildNonFlowSensitiveTransferer() {
673 return CFGMatchSwitchBuilder<TransferState<PointerNullabilityLattice>>()
674 .CaseOfCFGStmt<DeclRefExpr>(ast_matchers::declRefExpr(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800675 transferNonFlowSensitiveDeclRefExpr)
676 .CaseOfCFGStmt<MemberExpr>(ast_matchers::memberExpr(),
677 transferNonFlowSensitiveMemberExpr)
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800678 .CaseOfCFGStmt<CXXMemberCallExpr>(ast_matchers::cxxMemberCallExpr(),
679 transferNonFlowSensitiveMemberCallExpr)
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800680 .CaseOfCFGStmt<CastExpr>(ast_matchers::castExpr(),
681 transferNonFlowSensitiveCastExpr)
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800682 .CaseOfCFGStmt<MaterializeTemporaryExpr>(
683 ast_matchers::materializeTemporaryExpr(),
684 transferNonFlowSensitiveMaterializeTemporaryExpr)
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800685 .CaseOfCFGStmt<CallExpr>(ast_matchers::callExpr(),
686 transferNonFlowSensitiveCallExpr)
Googler2bccf742023-01-18 03:53:14 -0800687 .CaseOfCFGStmt<UnaryOperator>(ast_matchers::unaryOperator(),
688 transferNonFlowSensitiveUnaryOperator)
Martin Brænne66bc2432023-04-18 23:48:49 -0700689 .CaseOfCFGStmt<CXXNewExpr>(ast_matchers::cxxNewExpr(),
690 transferNonFlowSensitiveNewExpr)
Sam McCallf2b62b32023-05-02 06:45:40 -0700691 .CaseOfCFGStmt<ArraySubscriptExpr>(
692 ast_matchers::arraySubscriptExpr(),
693 transferNonFlowSensitiveArraySubscriptExpr)
Martin Brænne834d4b82023-05-15 07:07:05 -0700694 .CaseOfCFGStmt<CXXThisExpr>(ast_matchers::cxxThisExpr(),
695 transferNonFlowSensitiveThisExpr)
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800696 .Build();
697}
698
699auto buildFlowSensitiveTransferer() {
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800700 return CFGMatchSwitchBuilder<TransferState<PointerNullabilityLattice>>()
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800701 // Handles initialization of the null states of pointers.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800702 .CaseOfCFGStmt<Expr>(isAddrOf(), transferFlowSensitiveNotNullPointer)
Martin Brænne834d4b82023-05-15 07:07:05 -0700703 // TODO(mboehme): I believe we should be able to move handling of null
704 // pointers to the non-flow-sensitive part of the analysis.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800705 .CaseOfCFGStmt<Expr>(isNullPointerLiteral(),
706 transferFlowSensitiveNullPointer)
707 .CaseOfCFGStmt<CallExpr>(isCallExpr(), transferFlowSensitiveCallExpr)
708 .CaseOfCFGStmt<Expr>(isPointerExpr(), transferFlowSensitivePointer)
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800709 // Handles comparison between 2 pointers.
Wei Yi Tee217eb5f2022-09-15 03:18:28 -0700710 .CaseOfCFGStmt<BinaryOperator>(isPointerCheckBinOp(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800711 transferFlowSensitiveNullCheckComparison)
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800712 // Handles checking of pointer as boolean.
Wei Yi Tee217eb5f2022-09-15 03:18:28 -0700713 .CaseOfCFGStmt<Expr>(isImplicitCastPointerToBool(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800714 transferFlowSensitiveNullCheckImplicitCastPtrToBool)
Wei Yi Tee543af742022-06-01 06:52:24 -0700715 .Build();
716}
717} // namespace
718
Sam McCall7d9afee2023-06-27 01:43:24 -0700719PointerNullabilityAnalysis::PointerNullabilityAnalysis(ASTContext &Context)
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800720 : DataflowAnalysis<PointerNullabilityAnalysis, PointerNullabilityLattice>(
721 Context),
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800722 NonFlowSensitiveTransferer(buildNonFlowSensitiveTransferer()),
723 FlowSensitiveTransferer(buildFlowSensitiveTransferer()) {}
Wei Yi Tee543af742022-06-01 06:52:24 -0700724
Sam McCall74bf8642023-06-16 11:21:42 -0700725PointerTypeNullability PointerNullabilityAnalysis::assignNullabilityVariable(
Sam McCall7d9afee2023-06-27 01:43:24 -0700726 const ValueDecl *D, dataflow::Arena &A) {
Sam McCall74bf8642023-06-16 11:21:42 -0700727 auto [It, Inserted] = NFS.DeclTopLevelNullability.try_emplace(D);
728 if (Inserted) {
Dmitri Gribenkoaeb861f2023-07-07 10:05:40 -0700729 It->second.Nonnull = &A.makeAtomValue();
730 It->second.Nullable = &A.makeAtomValue();
Sam McCall74bf8642023-06-16 11:21:42 -0700731 }
732 return It->second;
733}
734
Sam McCall7d9afee2023-06-27 01:43:24 -0700735void PointerNullabilityAnalysis::transfer(const CFGElement &Elt,
736 PointerNullabilityLattice &Lattice,
737 Environment &Env) {
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800738 TransferState<PointerNullabilityLattice> State(Lattice, Env);
Googler9949b462023-02-15 05:09:07 -0800739 NonFlowSensitiveTransferer(Elt, getASTContext(), State);
740 FlowSensitiveTransferer(Elt, getASTContext(), State);
Wei Yi Tee543af742022-06-01 06:52:24 -0700741}
742
Sam McCall7d9afee2023-06-27 01:43:24 -0700743BoolValue &mergeBoolValues(BoolValue &Bool1, const Environment &Env1,
744 BoolValue &Bool2, const Environment &Env2,
745 Environment &MergedEnv) {
Wei Yi Tee721ee972022-08-11 01:14:54 -0700746 if (&Bool1 == &Bool2) {
747 return Bool1;
748 }
749
Dmitri Gribenkoaeb861f2023-07-07 10:05:40 -0700750 auto &A = MergedEnv.arena();
751 auto &MergedBool = A.makeAtomRef(A.makeAtom());
Wei Yi Tee721ee972022-08-11 01:14:54 -0700752
753 // If `Bool1` and `Bool2` is constrained to the same true / false value,
754 // `MergedBool` can be constrained similarly without needing to consider the
755 // path taken - this simplifies the flow condition tracked in `MergedEnv`.
756 // Otherwise, information about which path was taken is used to associate
757 // `MergedBool` with `Bool1` and `Bool2`.
758 if (Env1.flowConditionImplies(Bool1) && Env2.flowConditionImplies(Bool2)) {
759 MergedEnv.addToFlowCondition(MergedBool);
760 } else if (Env1.flowConditionImplies(Env1.makeNot(Bool1)) &&
761 Env2.flowConditionImplies(Env2.makeNot(Bool2))) {
Dmitri Gribenkoaeb861f2023-07-07 10:05:40 -0700762 MergedEnv.addToFlowCondition(A.makeNot(MergedBool));
Wei Yi Tee721ee972022-08-11 01:14:54 -0700763 } else {
764 // TODO(b/233582219): Flow conditions are not necessarily mutually
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800765 // exclusive, a fix is in order: https://reviews.llvm.org/D130270. Update
766 // this section when the patch is commited.
Dmitri Gribenkoaeb861f2023-07-07 10:05:40 -0700767 auto FC1 = Env1.getFlowConditionToken();
768 auto FC2 = Env2.getFlowConditionToken();
769 MergedEnv.addToFlowCondition(
770 A.makeOr(A.makeAnd(A.makeAtomRef(FC1),
771 A.makeEquals(MergedBool, Bool1.formula())),
772 A.makeAnd(A.makeAtomRef(FC2),
773 A.makeEquals(MergedBool, Bool2.formula()))));
Wei Yi Tee721ee972022-08-11 01:14:54 -0700774 }
Dmitri Gribenkoaeb861f2023-07-07 10:05:40 -0700775 return A.makeBoolValue(MergedBool);
Wei Yi Tee721ee972022-08-11 01:14:54 -0700776}
777
Sam McCall7d9afee2023-06-27 01:43:24 -0700778bool PointerNullabilityAnalysis::merge(QualType Type, const Value &Val1,
779 const Environment &Env1,
780 const Value &Val2,
781 const Environment &Env2,
782 Value &MergedVal,
783 Environment &MergedEnv) {
Wei Yi Tee721ee972022-08-11 01:14:54 -0700784 if (!Type->isAnyPointerType()) {
785 return false;
786 }
787
Martin Brænneed01de62023-06-13 05:45:21 -0700788 if (!hasPointerNullState(cast<PointerValue>(Val1)) ||
789 !hasPointerNullState(cast<PointerValue>(Val2))) {
790 return false;
791 }
792
Googlerf164e032023-05-18 08:38:51 -0700793 auto [Known1, Null1] = getPointerNullState(cast<PointerValue>(Val1));
794 auto [Known2, Null2] = getPointerNullState(cast<PointerValue>(Val2));
Wei Yi Tee721ee972022-08-11 01:14:54 -0700795
Sam McCall7d9afee2023-06-27 01:43:24 -0700796 auto &Known = mergeBoolValues(Known1, Env1, Known2, Env2, MergedEnv);
797 auto &Null = mergeBoolValues(Null1, Env1, Null2, Env2, MergedEnv);
Wei Yi Tee721ee972022-08-11 01:14:54 -0700798
Dani Ferreira Franco Mouraa0649822022-11-11 07:55:05 -0800799 initPointerNullState(cast<PointerValue>(MergedVal), MergedEnv, &Known, &Null);
Wei Yi Tee721ee972022-08-11 01:14:54 -0700800
801 return true;
Wei Yi Tee543af742022-06-01 06:52:24 -0700802}
Sam McCall5fc2a802023-05-02 05:41:27 -0700803
Sam McCall4f6be422023-06-27 02:51:22 -0700804} // namespace clang::tidy::nullability