blob: b2211e47ad76fb5cea8c60db32805dea1876c409 [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"
Wei Yi Tee543af742022-06-01 06:52:24 -070018#include "clang/AST/Expr.h"
Wei Yi Tee1cd62af2022-06-09 00:56:46 -070019#include "clang/AST/OperationKinds.h"
20#include "clang/AST/Stmt.h"
21#include "clang/AST/Type.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070022#include "clang/ASTMatchers/ASTMatchFinder.h"
Martin Brænnec4903062023-04-24 23:40:36 -070023#include "clang/ASTMatchers/ASTMatchers.h"
Wei Yi Tee217eb5f2022-09-15 03:18:28 -070024#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070025#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070026#include "clang/Analysis/FlowSensitive/Value.h"
27#include "clang/Basic/LLVM.h"
Wei Yi Teef5e8e572022-08-02 11:31:12 -070028#include "clang/Basic/Specifiers.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070029
30namespace clang {
31namespace tidy {
32namespace nullability {
33
34using ast_matchers::MatchFinder;
35using dataflow::BoolValue;
Wei Yi Tee217eb5f2022-09-15 03:18:28 -070036using dataflow::CFGMatchSwitchBuilder;
Wei Yi Tee543af742022-06-01 06:52:24 -070037using dataflow::Environment;
Wei Yi Tee721ee972022-08-11 01:14:54 -070038using dataflow::PointerValue;
Wei Yi Tee543af742022-06-01 06:52:24 -070039using dataflow::TransferState;
40using dataflow::Value;
41
42namespace {
43
Sam McCalld127f932023-05-02 07:15:27 -070044TypeNullability prepend(NullabilityKind Head, const TypeNullability& Tail) {
45 TypeNullability Result = {Head};
Googler2bccf742023-01-18 03:53:14 -080046 Result.insert(Result.end(), Tail.begin(), Tail.end());
47 return Result;
48}
49
Googler5ef1bdf2023-01-18 04:01:15 -080050void computeNullability(const Expr* E,
51 TransferState<PointerNullabilityLattice>& State,
Sam McCalld127f932023-05-02 07:15:27 -070052 std::function<TypeNullability()> Compute) {
Googler5ef1bdf2023-01-18 04:01:15 -080053 (void)State.Lattice.insertExprNullabilityIfAbsent(E, [&] {
54 auto Nullability = Compute();
55 if (unsigned ExpectedSize = countPointersInType(E);
56 ExpectedSize != Nullability.size()) {
57 // A nullability vector must have one entry per pointer in the type.
58 // If this is violated, we probably failed to handle some AST node.
Martin Brænne9d2afac2023-04-06 05:20:46 -070059 llvm::dbgs()
60 << "=== Nullability vector has wrong number of entries: ===\n";
Googler5ef1bdf2023-01-18 04:01:15 -080061 llvm::dbgs() << "Expression: \n";
62 dump(E, llvm::dbgs());
63 llvm::dbgs() << "\nNullability (" << Nullability.size()
64 << " pointers): " << nullabilityToString(Nullability)
65 << "\n";
66 llvm::dbgs() << "\nType (" << ExpectedSize << " pointers): \n";
67 dump(exprType(E), llvm::dbgs());
68 llvm::dbgs() << "=================================\n";
69
70 // We can't meaningfully interpret the vector, so discard it.
71 // TODO: fix all broken cases and upgrade to CHECK or DCHECK or so.
72 Nullability.assign(ExpectedSize, NullabilityKind::Unspecified);
73 }
74 return Nullability;
75 });
76}
77
Sam McCall5fc2a802023-05-02 05:41:27 -070078// Returns the computed nullability for a subexpr of the current expression.
79// This is always available as we compute bottom-up.
Sam McCalld127f932023-05-02 07:15:27 -070080const TypeNullability& getNullabilityForChild(
Sam McCall5fc2a802023-05-02 05:41:27 -070081 const Expr* E, TransferState<PointerNullabilityLattice>& State) {
82 return State.Lattice.insertExprNullabilityIfAbsent(E, [&] {
83 // Since we process child nodes before parents, we should already have
84 // computed the child nullability. However, this is not true in all test
85 // cases. So, we return unspecified nullability annotations.
86 // TODO: fix this issue, and CHECK() instead.
87 llvm::dbgs() << "=== Missing child nullability: ===\n";
88 dump(E, llvm::dbgs());
89 llvm::dbgs() << "==================================\n";
90
91 return unspecifiedNullability(E);
92 });
93}
94
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -080095/// Compute the nullability annotation of type `T`, which contains types
96/// originally written as a class template type parameter.
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -080097///
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -080098/// Example:
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -080099///
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800100/// \code
101/// template <typename F, typename S>
102/// struct pair {
103/// S *_Nullable getNullablePtrToSecond();
104/// };
105/// \endcode
106///
107/// Consider the following member call:
108///
109/// \code
110/// pair<int *, int *_Nonnull> x;
111/// x.getNullablePtrToSecond();
112/// \endcode
113///
114/// The class template specialization `x` has the following substitutions:
115///
116/// F=int *, whose nullability is [_Unspecified]
117/// S=int * _Nonnull, whose nullability is [_Nonnull]
118///
119/// The return type of the member call `x.getNullablePtrToSecond()` is
120/// S * _Nullable.
121///
122/// When we call `substituteNullabilityAnnotationsInClassTemplate` with the type
123/// `S * _Nullable` and the `base` node of the member call (in this case, a
124/// `DeclRefExpr`), it returns the nullability of the given type after applying
125/// substitutions, which in this case is [_Nullable, _Nonnull].
Sam McCalld127f932023-05-02 07:15:27 -0700126TypeNullability substituteNullabilityAnnotationsInClassTemplate(
127 QualType T, const TypeNullability& BaseNullabilityAnnotations,
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -0800128 QualType BaseType) {
Sam McCall932b7432023-01-23 04:41:22 -0800129 return getNullabilityAnnotationsFromType(
130 T,
131 [&](const SubstTemplateTypeParmType* ST)
Sam McCalld127f932023-05-02 07:15:27 -0700132 -> std::optional<TypeNullability> {
Sam McCall28ab01a2023-01-23 05:15:48 -0800133 // The class specialization that is BaseType and owns ST.
134 const ClassTemplateSpecializationDecl* Specialization = nullptr;
135 if (auto RT = BaseType->getAs<RecordType>())
136 Specialization =
137 dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
138 // TODO: handle nested templates, where associated decl != base type
139 // (e.g. PointerNullabilityTest.MemberFunctionTemplateOfTemplateStruct)
140 if (!Specialization || Specialization != ST->getAssociatedDecl())
141 return std::nullopt;
142
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800143 unsigned ArgIndex = ST->getIndex();
Sam McCall28ab01a2023-01-23 05:15:48 -0800144 auto TemplateArgs = Specialization->getTemplateArgs().asArray();
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800145
Sam McCalla45d2602023-04-28 13:20:15 -0700146 unsigned PointerCount =
147 countPointersInType(Specialization->getDeclContext());
Sam McCall28ab01a2023-01-23 05:15:48 -0800148 for (auto TA : TemplateArgs.take_front(ArgIndex)) {
149 PointerCount += countPointersInType(TA);
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800150 }
Sam McCall28ab01a2023-01-23 05:15:48 -0800151 unsigned SliceSize = countPointersInType(TemplateArgs[ArgIndex]);
Sam McCalld127f932023-05-02 07:15:27 -0700152 return ArrayRef(BaseNullabilityAnnotations)
153 .slice(PointerCount, SliceSize)
154 .vec();
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800155 });
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800156}
157
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800158/// Compute nullability annotations of `T`, which might contain template type
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800159/// variable substitutions bound by the call `CE`.
160///
161/// Example:
162///
163/// \code
164/// template<typename F, typename S>
165/// std::pair<S, F> flip(std::pair<F, S> p);
166/// \endcode
167///
168/// Consider the following CallExpr:
169///
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800170/// \code
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800171/// flip<int * _Nonnull, int * _Nullable>(std::make_pair(&x, &y));
Dani Ferreira Franco Moura82c17582023-01-17 10:58:53 -0800172/// \endcode
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800173///
174/// This CallExpr has the following substitutions:
175/// F=int * _Nonnull, whose nullability is [_Nonnull]
176/// S=int * _Nullable, whose nullability is [_Nullable]
177///
178/// The return type of this CallExpr is `std::pair<S, F>`.
179///
180/// When we call `substituteNullabilityAnnotationsInFunctionTemplate` with the
181/// type `std::pair<S, F>` and the above CallExpr, it returns the nullability
182/// the given type after applying substitutions, which in this case is
183/// [_Nullable, _Nonnull].
Sam McCalld127f932023-05-02 07:15:27 -0700184TypeNullability substituteNullabilityAnnotationsInFunctionTemplate(
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800185 QualType T, const CallExpr* CE) {
Sam McCall932b7432023-01-23 04:41:22 -0800186 return getNullabilityAnnotationsFromType(
187 T,
188 [&](const SubstTemplateTypeParmType* ST)
Sam McCalld127f932023-05-02 07:15:27 -0700189 -> std::optional<TypeNullability> {
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800190 // TODO: Handle calls that use template argument deduction.
Lukasz Anforowicz60ed6c82023-04-26 12:05:26 -0700191 // TODO: Handle nested templates (...->getDepth() > 0).
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800192 if (auto* DRE =
193 dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreImpCasts());
Martin Brænnec4903062023-04-24 23:40:36 -0700194 DRE != nullptr && ST->getReplacedParameter()->getDepth() == 0 &&
Martin Brænne8cdb0b12023-04-27 03:47:50 -0700195 // Some or all of the template arguments may be deduced, and we
196 // won't see those on the `DeclRefExpr`. If the template argument
197 // was deduced, we don't have any sugar for it.
Martin Brænne684cf702023-04-28 04:36:23 -0700198 // TODO(b/268348533): Can we somehow obtain it from the function
199 // param it was deduced from?
200 // TODO(b/268345783): This check, as well as the index into
201 // `template_arguments` below, may be incorrect in the presence of
202 // parameters packs. In function templates, parameter packs may
203 // appear anywhere in the parameter list. The index may therefore
204 // refer to one of the pack arguments, but we might incorrectly
205 // interpret it as referring to an argument that follows the pack.
Martin Brænne8cdb0b12023-04-27 03:47:50 -0700206 ST->getIndex() < DRE->template_arguments().size()) {
Martin Brænne61d4e362023-04-27 01:07:59 -0700207 TypeSourceInfo* TSI =
208 DRE->template_arguments()[ST->getIndex()].getTypeSourceInfo();
209 if (TSI == nullptr) return std::nullopt;
210 return getNullabilityAnnotationsFromType(TSI->getType());
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800211 }
Sam McCall932b7432023-01-23 04:41:22 -0800212 return std::nullopt;
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800213 });
Dani Ferreira Franco Moura7ca32fc2022-11-24 04:19:16 -0800214}
215
Dani Ferreira Franco Moura1d41c112022-12-21 08:43:32 -0800216NullabilityKind getPointerNullability(const Expr* E,
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800217 PointerNullabilityAnalysis::Lattice& L) {
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800218 QualType ExprType = E->getType();
Googlerbad70522023-01-31 04:37:38 -0800219 std::optional<NullabilityKind> Nullability = ExprType->getNullability();
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800220
221 // If the expression's type does not contain nullability information, it may
222 // be a template instantiation. Look up the nullability in the
223 // `ExprToNullability` map.
224 if (Nullability.value_or(NullabilityKind::Unspecified) ==
225 NullabilityKind::Unspecified) {
226 if (auto MaybeNullability = L.getExprNullability(E)) {
227 if (!MaybeNullability->empty()) {
228 // Return the nullability of the topmost pointer in the type.
229 Nullability = (*MaybeNullability)[0];
230 }
231 }
232 }
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800233 return Nullability.value_or(NullabilityKind::Unspecified);
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800234}
235
Dani Ferreira Franco Moura1d41c112022-12-21 08:43:32 -0800236void initPointerFromAnnotations(
237 PointerValue& PointerVal, const Expr* E,
238 TransferState<PointerNullabilityLattice>& State) {
239 NullabilityKind Nullability = getPointerNullability(E, State.Lattice);
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700240 switch (Nullability) {
241 case NullabilityKind::NonNull:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800242 initNotNullPointer(PointerVal, State.Env);
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700243 break;
Wei Yi Teeae43f392022-08-02 11:33:23 -0700244 case NullabilityKind::Nullable:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800245 initNullablePointer(PointerVal, State.Env);
Wei Yi Teeae43f392022-08-02 11:33:23 -0700246 break;
247 default:
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800248 initUnknownPointer(PointerVal, State.Env);
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700249 }
250}
251
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800252void transferFlowSensitiveNullPointer(
253 const Expr* NullPointer, const MatchFinder::MatchResult&,
254 TransferState<PointerNullabilityLattice>& State) {
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700255 if (auto* PointerVal = getPointerValueFromExpr(NullPointer, State.Env)) {
256 initNullPointer(*PointerVal, State.Env);
257 }
258}
259
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800260void transferFlowSensitiveNotNullPointer(
261 const Expr* NotNullPointer, const MatchFinder::MatchResult&,
262 TransferState<PointerNullabilityLattice>& State) {
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700263 if (auto* PointerVal = getPointerValueFromExpr(NotNullPointer, State.Env)) {
264 initNotNullPointer(*PointerVal, State.Env);
265 }
266}
267
Sam McCall74bf8642023-06-16 11:21:42 -0700268const PointerTypeNullability* getOverriddenNullability(
269 const Expr* E, PointerNullabilityLattice& Lattice) {
270 if (const auto* DRE = dyn_cast<DeclRefExpr>(E))
271 return Lattice.getDeclNullability(DRE->getDecl());
272 if (const auto* ME = dyn_cast<MemberExpr>(E))
273 return Lattice.getDeclNullability(ME->getMemberDecl());
274 return nullptr;
275}
276
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800277void transferFlowSensitivePointer(
278 const Expr* PointerExpr, const MatchFinder::MatchResult& Result,
279 TransferState<PointerNullabilityLattice>& State) {
Sam McCall74bf8642023-06-16 11:21:42 -0700280 auto& Env = State.Env;
281 if (auto* PointerVal = getPointerValueFromExpr(PointerExpr, Env)) {
282 if (auto* Override = getOverriddenNullability(PointerExpr, State.Lattice)) {
283 // is_known = (nonnull | nullable)
284 initPointerNullState(
285 *PointerVal, Env,
286 &Env.makeOr(*Override->Nonnull, *Override->Nullable));
287 // nonnull => !is_null
288 auto [IsKnown, IsNull] = getPointerNullState(*PointerVal);
289 Env.addToFlowCondition(
290 Env.makeImplication(*Override->Nonnull, Env.makeNot(IsNull)));
291 } else {
292 initPointerFromAnnotations(*PointerVal, PointerExpr, State);
293 }
Wei Yi Teef5e8e572022-08-02 11:31:12 -0700294 }
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700295}
296
Wei Yi Tee8b58e192022-08-02 10:15:40 -0700297// TODO(b/233582219): Implement promotion of nullability knownness for initially
298// unknown pointers when there is evidence that it is nullable, for example
299// when the pointer is compared to nullptr, or casted to boolean.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800300void transferFlowSensitiveNullCheckComparison(
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800301 const BinaryOperator* BinaryOp, const MatchFinder::MatchResult& result,
302 TransferState<PointerNullabilityLattice>& State) {
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700303 // Boolean representing the comparison between the two pointer values,
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800304 // automatically created by the dataflow framework.
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700305 auto& PointerComparison =
Martin Brænne0da58852023-05-23 06:43:57 -0700306 *cast<BoolValue>(State.Env.getValueStrict(*BinaryOp));
Wei Yi Tee543af742022-06-01 06:52:24 -0700307
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700308 CHECK(BinaryOp->getOpcode() == BO_EQ || BinaryOp->getOpcode() == BO_NE);
309 auto& PointerEQ = BinaryOp->getOpcode() == BO_EQ
310 ? PointerComparison
311 : State.Env.makeNot(PointerComparison);
312 auto& PointerNE = BinaryOp->getOpcode() == BO_EQ
313 ? State.Env.makeNot(PointerComparison)
314 : PointerComparison;
315
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700316 auto* LHS = getPointerValueFromExpr(BinaryOp->getLHS(), State.Env);
317 auto* RHS = getPointerValueFromExpr(BinaryOp->getRHS(), State.Env);
318
319 if (!LHS || !RHS) return;
320
Googlerb1c66812023-06-09 10:20:46 -0700321 auto& LHSNull = getPointerNullState(*LHS).second;
322 auto& RHSNull = getPointerNullState(*RHS).second;
323 auto& LHSNotNull = State.Env.makeNot(LHSNull);
324 auto& RHSNotNull = State.Env.makeNot(RHSNull);
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700325
Wei Yi Tee06f06962022-08-02 09:49:50 -0700326 // nullptr == nullptr
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700327 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700328 State.Env.makeAnd(LHSNull, RHSNull), PointerEQ));
Wei Yi Tee06f06962022-08-02 09:49:50 -0700329 // nullptr != notnull
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700330 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700331 State.Env.makeAnd(LHSNull, RHSNotNull), PointerNE));
Wei Yi Tee06f06962022-08-02 09:49:50 -0700332 // notnull != nullptr
Wei Yi Tee1cd62af2022-06-09 00:56:46 -0700333 State.Env.addToFlowCondition(State.Env.makeImplication(
Googlerb1c66812023-06-09 10:20:46 -0700334 State.Env.makeAnd(LHSNotNull, RHSNull), PointerNE));
Wei Yi Tee543af742022-06-01 06:52:24 -0700335}
336
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800337void transferFlowSensitiveNullCheckImplicitCastPtrToBool(
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800338 const Expr* CastExpr, const MatchFinder::MatchResult&,
339 TransferState<PointerNullabilityLattice>& State) {
Wei Yi Tee8374c8f2022-08-11 01:18:41 -0700340 auto* PointerVal =
341 getPointerValueFromExpr(CastExpr->IgnoreImplicit(), State.Env);
342 if (!PointerVal) return;
343
Googlerf164e032023-05-18 08:38:51 -0700344 auto [PointerKnown, PointerNull] = getPointerNullState(*PointerVal);
Martin Brænne0da58852023-05-23 06:43:57 -0700345 State.Env.setValueStrict(*CastExpr, State.Env.makeNot(PointerNull));
Wei Yi Tee543af742022-06-01 06:52:24 -0700346}
347
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800348void transferFlowSensitiveCallExpr(
349 const CallExpr* CallExpr, const MatchFinder::MatchResult& Result,
350 TransferState<PointerNullabilityLattice>& State) {
Martin Brænnec307b1f2023-04-20 07:16:35 -0700351 // The dataflow framework itself does not create values for `CallExpr`s.
352 // However, we need these in some cases, so we produce them ourselves.
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700353
Martin Brænne0da58852023-05-23 06:43:57 -0700354 dataflow::StorageLocation* Loc = nullptr;
355 if (CallExpr->isGLValue()) {
356 // The function returned a reference. Create a storage location for the
357 // expression so that if code creates a pointer from the reference, we will
358 // produce a `PointerValue`.
359 Loc = State.Env.getStorageLocationStrict(*CallExpr);
360 if (!Loc) {
361 // This is subtle: We call `createStorageLocation(QualType)`, not
362 // `createStorageLocation(const Expr &)`, so that we create a new
363 // storage location every time.
364 Loc = &State.Env.createStorageLocation(CallExpr->getType());
365 State.Env.setStorageLocationStrict(*CallExpr, *Loc);
366 }
367 }
368
Martin Brænnec307b1f2023-04-20 07:16:35 -0700369 if (CallExpr->getType()->isAnyPointerType()) {
370 // Create a pointer so that we can attach nullability to it and have the
371 // nullability propagate with the pointer.
372 auto* PointerVal = getPointerValueFromExpr(CallExpr, State.Env);
373 if (!PointerVal) {
374 PointerVal =
375 cast<PointerValue>(State.Env.createValue(CallExpr->getType()));
Martin Brænnec307b1f2023-04-20 07:16:35 -0700376 }
377 initPointerFromAnnotations(*PointerVal, CallExpr, State);
Martin Brænne0da58852023-05-23 06:43:57 -0700378
379 if (Loc != nullptr)
380 State.Env.setValue(*Loc, *PointerVal);
381 else
382 // `Loc` is set iff `CallExpr` is a glvalue, so we know here that it must
383 // be a prvalue.
384 State.Env.setValueStrict(*CallExpr, *PointerVal);
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700385 }
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700386}
387
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800388void transferNonFlowSensitiveDeclRefExpr(
389 const DeclRefExpr* DRE, const MatchFinder::MatchResult& MR,
390 TransferState<PointerNullabilityLattice>& State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800391 computeNullability(DRE, State, [&] {
392 return getNullabilityAnnotationsFromType(DRE->getType());
393 });
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800394}
395
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800396void transferNonFlowSensitiveMemberExpr(
397 const MemberExpr* ME, const MatchFinder::MatchResult& MR,
398 TransferState<PointerNullabilityLattice>& State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800399 computeNullability(ME, State, [&]() {
Googlerd4437312023-01-17 15:10:29 -0800400 auto BaseNullability = getNullabilityForChild(ME->getBase(), State);
401 QualType MemberType = ME->getType();
402 // When a MemberExpr is a part of a member function call
403 // (a child of CXXMemberCallExpr), the MemberExpr models a
404 // partially-applied member function, which isn't a real C++ construct.
405 // The AST does not provide rich type information for such MemberExprs.
406 // Instead, the AST specifies a placeholder type, specifically
407 // BuiltinType::BoundMember. So we have to look at the type of the member
408 // function declaration.
409 if (ME->hasPlaceholderType(BuiltinType::BoundMember)) {
410 MemberType = ME->getMemberDecl()->getType();
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800411 }
Googlerd4437312023-01-17 15:10:29 -0800412 return substituteNullabilityAnnotationsInClassTemplate(
413 MemberType, BaseNullability, ME->getBase()->getType());
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800414 });
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800415}
416
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800417void transferNonFlowSensitiveMemberCallExpr(
418 const CXXMemberCallExpr* MCE, const MatchFinder::MatchResult& MR,
419 TransferState<PointerNullabilityLattice>& State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800420 computeNullability(MCE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700421 return ArrayRef(getNullabilityForChild(MCE->getCallee(), State))
Martin Brænnec4903062023-04-24 23:40:36 -0700422 .take_front(countPointersInType(MCE))
423 .vec();
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800424 });
425}
426
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800427void transferNonFlowSensitiveCastExpr(
428 const CastExpr* CE, const MatchFinder::MatchResult& MR,
429 TransferState<PointerNullabilityLattice>& State) {
Sam McCalld127f932023-05-02 07:15:27 -0700430 computeNullability(CE, State, [&]() -> TypeNullability {
Sam McCall2245db22023-04-17 06:50:25 -0700431 // Most casts that can convert ~unrelated types drop nullability in general.
432 // As a special case, preserve nullability of outer pointer types.
433 // For example, int* p; (void*)p; is a BitCast, but preserves nullability.
Sam McCalld127f932023-05-02 07:15:27 -0700434 auto PreserveTopLevelPointers = [&](TypeNullability V) {
Sam McCall2245db22023-04-17 06:50:25 -0700435 auto ArgNullability = getNullabilityForChild(CE->getSubExpr(), State);
436 const PointerType* ArgType = dyn_cast<PointerType>(
437 CE->getSubExpr()->getType().getCanonicalType().getTypePtr());
438 const PointerType* CastType =
439 dyn_cast<PointerType>(CE->getType().getCanonicalType().getTypePtr());
440 for (int I = 0; ArgType && CastType; ++I) {
441 V[I] = ArgNullability[I];
442 ArgType = dyn_cast<PointerType>(ArgType->getPointeeType().getTypePtr());
443 CastType =
444 dyn_cast<PointerType>(CastType->getPointeeType().getTypePtr());
445 }
446 return V;
447 };
448
449 switch (CE->getCastKind()) {
450 // Casts between unrelated types: we can't say anything about nullability.
451 case CK_LValueBitCast:
452 case CK_BitCast:
453 case CK_LValueToRValueBitCast:
454 return PreserveTopLevelPointers(unspecifiedNullability(CE));
455
456 // Casts between equivalent types.
457 case CK_LValueToRValue:
458 case CK_NoOp:
459 case CK_AtomicToNonAtomic:
460 case CK_NonAtomicToAtomic:
461 case CK_AddressSpaceConversion:
Sam McCalld127f932023-05-02 07:15:27 -0700462 return getNullabilityForChild(CE->getSubExpr(), State);
Sam McCall2245db22023-04-17 06:50:25 -0700463
464 // Controlled conversions between types
465 // TODO: these should be doable somehow
466 case CK_BaseToDerived:
467 case CK_DerivedToBase:
468 case CK_UncheckedDerivedToBase:
469 return PreserveTopLevelPointers(unspecifiedNullability(CE));
470 case CK_UserDefinedConversion:
471 case CK_ConstructorConversion:
472 return unspecifiedNullability(CE);
473
474 case CK_Dynamic: {
475 auto Result = unspecifiedNullability(CE);
476 // A dynamic_cast to pointer is null if the runtime check fails.
477 if (isa<PointerType>(CE->getType().getCanonicalType()))
478 Result.front() = NullabilityKind::Nullable;
479 return Result;
480 }
481
482 // Primitive values have no nullability.
483 case CK_ToVoid:
484 case CK_MemberPointerToBoolean:
485 case CK_PointerToBoolean:
486 case CK_PointerToIntegral:
487 case CK_IntegralCast:
488 case CK_IntegralToBoolean:
489 case CK_IntegralToFloating:
490 case CK_FloatingToFixedPoint:
491 case CK_FixedPointToFloating:
492 case CK_FixedPointCast:
493 case CK_FixedPointToIntegral:
494 case CK_IntegralToFixedPoint:
495 case CK_FixedPointToBoolean:
496 case CK_FloatingToIntegral:
497 case CK_FloatingToBoolean:
498 case CK_BooleanToSignedIntegral:
499 case CK_FloatingCast:
500 case CK_FloatingRealToComplex:
501 case CK_FloatingComplexToReal:
502 case CK_FloatingComplexToBoolean:
503 case CK_FloatingComplexCast:
504 case CK_FloatingComplexToIntegralComplex:
505 case CK_IntegralRealToComplex:
506 case CK_IntegralComplexToReal:
507 case CK_IntegralComplexToBoolean:
508 case CK_IntegralComplexCast:
509 case CK_IntegralComplexToFloatingComplex:
510 return {};
511
512 // This can definitely be null!
513 case CK_NullToPointer: {
514 auto Nullability = getNullabilityAnnotationsFromType(CE->getType());
Martin Brænne60e4c362023-06-21 02:44:41 -0700515 // Despite the name `NullToPointer`, the destination type of the cast
516 // may be `nullptr_t` (which is, itself, not a pointer type).
517 if (!CE->getType()->isNullPtrType())
518 Nullability.front() = NullabilityKind::Nullable;
Sam McCall2245db22023-04-17 06:50:25 -0700519 return Nullability;
520 }
521
522 // Pointers out of thin air, who knows?
523 case CK_IntegralToPointer:
524 return unspecifiedNullability(CE);
525
526 // Decayed objects are never null.
527 case CK_ArrayToPointerDecay:
528 case CK_FunctionToPointerDecay:
529 case CK_BuiltinFnToFnPtr:
530 return prepend(NullabilityKind::NonNull,
531 getNullabilityForChild(CE->getSubExpr(), State));
532
533 // TODO: what is our model of member pointers?
534 case CK_BaseToDerivedMemberPointer:
535 case CK_DerivedToBaseMemberPointer:
536 case CK_NullToMemberPointer:
537 case CK_ReinterpretMemberPointer:
538 case CK_ToUnion: // and unions?
539 return unspecifiedNullability(CE);
540
541 // TODO: Non-C/C++ constructs, do we care about these?
542 case CK_CPointerToObjCPointerCast:
543 case CK_ObjCObjectLValueCast:
544 case CK_MatrixCast:
545 case CK_VectorSplat:
546 case CK_BlockPointerToObjCPointerCast:
547 case CK_AnyPointerToBlockPointerCast:
548 case CK_ARCProduceObject:
549 case CK_ARCConsumeObject:
550 case CK_ARCReclaimReturnedObject:
551 case CK_ARCExtendBlockObject:
552 case CK_CopyAndAutoreleaseBlockObject:
553 case CK_ZeroToOCLOpaqueType:
554 case CK_IntToOCLSampler:
555 return unspecifiedNullability(CE);
556
557 case CK_Dependent:
558 CHECK(false) << "Shouldn't see dependent casts here?";
559 }
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800560 });
561}
562
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800563void transferNonFlowSensitiveMaterializeTemporaryExpr(
564 const MaterializeTemporaryExpr* MTE, const MatchFinder::MatchResult& MR,
565 TransferState<PointerNullabilityLattice>& State) {
Googler5ef1bdf2023-01-18 04:01:15 -0800566 computeNullability(MTE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700567 return getNullabilityForChild(MTE->getSubExpr(), State);
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800568 });
569}
570
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800571void transferNonFlowSensitiveCallExpr(
572 const CallExpr* CE, const MatchFinder::MatchResult& MR,
573 TransferState<PointerNullabilityLattice>& State) {
574 // TODO: Check CallExpr arguments in the diagnoser against the nullability of
575 // parameters.
Googler5ef1bdf2023-01-18 04:01:15 -0800576 computeNullability(CE, State, [&]() {
Martin Brænnec4903062023-04-24 23:40:36 -0700577 // TODO(mboehme): Instead of relying on Clang to propagate nullability sugar
578 // to the `CallExpr`'s type, we should extract nullability directly from the
579 // callee `Expr .
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800580 return substituteNullabilityAnnotationsInFunctionTemplate(CE->getType(),
581 CE);
582 });
583}
584
Googler2bccf742023-01-18 03:53:14 -0800585void transferNonFlowSensitiveUnaryOperator(
586 const UnaryOperator* UO, const MatchFinder::MatchResult& MR,
587 TransferState<PointerNullabilityLattice>& State) {
Sam McCalld127f932023-05-02 07:15:27 -0700588 computeNullability(UO, State, [&]() -> TypeNullability {
Googler5ef1bdf2023-01-18 04:01:15 -0800589 switch (UO->getOpcode()) {
590 case UO_AddrOf:
591 return prepend(NullabilityKind::NonNull,
592 getNullabilityForChild(UO->getSubExpr(), State));
593 case UO_Deref:
Sam McCalld127f932023-05-02 07:15:27 -0700594 return ArrayRef(getNullabilityForChild(UO->getSubExpr(), State))
Googler5ef1bdf2023-01-18 04:01:15 -0800595 .drop_front()
596 .vec();
Googler2bccf742023-01-18 03:53:14 -0800597
Googler5ef1bdf2023-01-18 04:01:15 -0800598 case UO_PostInc:
599 case UO_PostDec:
600 case UO_PreInc:
601 case UO_PreDec:
602 case UO_Plus:
603 case UO_Minus:
604 case UO_Not:
605 case UO_LNot:
606 case UO_Real:
607 case UO_Imag:
608 case UO_Extension:
609 return getNullabilityForChild(UO->getSubExpr(), State);
Googler2bccf742023-01-18 03:53:14 -0800610
Googler5ef1bdf2023-01-18 04:01:15 -0800611 case UO_Coawait:
612 // TODO: work out what to do here!
613 return unspecifiedNullability(UO);
614 }
615 });
Googler2bccf742023-01-18 03:53:14 -0800616}
617
Martin Brænne66bc2432023-04-18 23:48:49 -0700618void transferNonFlowSensitiveNewExpr(
619 const CXXNewExpr* NE, const MatchFinder::MatchResult& MR,
620 TransferState<PointerNullabilityLattice>& State) {
621 computeNullability(NE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700622 TypeNullability result = getNullabilityAnnotationsFromType(NE->getType());
Martin Brænne66bc2432023-04-18 23:48:49 -0700623 result.front() = NE->shouldNullCheckAllocation() ? NullabilityKind::Nullable
624 : NullabilityKind::NonNull;
625 return result;
626 });
627}
628
Sam McCallf2b62b32023-05-02 06:45:40 -0700629void transferNonFlowSensitiveArraySubscriptExpr(
630 const ArraySubscriptExpr* ASE, const MatchFinder::MatchResult& MR,
631 TransferState<PointerNullabilityLattice>& State) {
632 computeNullability(ASE, State, [&]() {
Sam McCalld127f932023-05-02 07:15:27 -0700633 auto& BaseNullability = getNullabilityForChild(ASE->getBase(), State);
Sam McCallf2b62b32023-05-02 06:45:40 -0700634 CHECK(ASE->getBase()->getType()->isAnyPointerType());
Sam McCalld127f932023-05-02 07:15:27 -0700635 return ArrayRef(BaseNullability).slice(1).vec();
Sam McCallf2b62b32023-05-02 06:45:40 -0700636 });
637}
638
Martin Brænne834d4b82023-05-15 07:07:05 -0700639void transferNonFlowSensitiveThisExpr(
640 const CXXThisExpr* TE, const MatchFinder::MatchResult& MR,
641 TransferState<PointerNullabilityLattice>& State) {
642 computeNullability(TE, State, [&]() {
643 TypeNullability result = getNullabilityAnnotationsFromType(TE->getType());
644 result.front() = NullabilityKind::NonNull;
645 return result;
646 });
647}
648
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800649auto buildNonFlowSensitiveTransferer() {
650 return CFGMatchSwitchBuilder<TransferState<PointerNullabilityLattice>>()
651 .CaseOfCFGStmt<DeclRefExpr>(ast_matchers::declRefExpr(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800652 transferNonFlowSensitiveDeclRefExpr)
653 .CaseOfCFGStmt<MemberExpr>(ast_matchers::memberExpr(),
654 transferNonFlowSensitiveMemberExpr)
Dani Ferreira Franco Moura826c8b32023-01-04 07:24:10 -0800655 .CaseOfCFGStmt<CXXMemberCallExpr>(ast_matchers::cxxMemberCallExpr(),
656 transferNonFlowSensitiveMemberCallExpr)
Dani Ferreira Franco Moura933a69b2023-01-12 11:03:42 -0800657 .CaseOfCFGStmt<CastExpr>(ast_matchers::castExpr(),
658 transferNonFlowSensitiveCastExpr)
Dani Ferreira Franco Mouraaa2211d2023-01-17 09:40:30 -0800659 .CaseOfCFGStmt<MaterializeTemporaryExpr>(
660 ast_matchers::materializeTemporaryExpr(),
661 transferNonFlowSensitiveMaterializeTemporaryExpr)
Dani Ferreira Franco Mouraa29a2a02023-01-17 10:57:45 -0800662 .CaseOfCFGStmt<CallExpr>(ast_matchers::callExpr(),
663 transferNonFlowSensitiveCallExpr)
Googler2bccf742023-01-18 03:53:14 -0800664 .CaseOfCFGStmt<UnaryOperator>(ast_matchers::unaryOperator(),
665 transferNonFlowSensitiveUnaryOperator)
Martin Brænne66bc2432023-04-18 23:48:49 -0700666 .CaseOfCFGStmt<CXXNewExpr>(ast_matchers::cxxNewExpr(),
667 transferNonFlowSensitiveNewExpr)
Sam McCallf2b62b32023-05-02 06:45:40 -0700668 .CaseOfCFGStmt<ArraySubscriptExpr>(
669 ast_matchers::arraySubscriptExpr(),
670 transferNonFlowSensitiveArraySubscriptExpr)
Martin Brænne834d4b82023-05-15 07:07:05 -0700671 .CaseOfCFGStmt<CXXThisExpr>(ast_matchers::cxxThisExpr(),
672 transferNonFlowSensitiveThisExpr)
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800673 .Build();
674}
675
676auto buildFlowSensitiveTransferer() {
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800677 return CFGMatchSwitchBuilder<TransferState<PointerNullabilityLattice>>()
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800678 // Handles initialization of the null states of pointers.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800679 .CaseOfCFGStmt<Expr>(isAddrOf(), transferFlowSensitiveNotNullPointer)
Martin Brænne834d4b82023-05-15 07:07:05 -0700680 // TODO(mboehme): I believe we should be able to move handling of null
681 // pointers to the non-flow-sensitive part of the analysis.
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800682 .CaseOfCFGStmt<Expr>(isNullPointerLiteral(),
683 transferFlowSensitiveNullPointer)
684 .CaseOfCFGStmt<CallExpr>(isCallExpr(), transferFlowSensitiveCallExpr)
685 .CaseOfCFGStmt<Expr>(isPointerExpr(), transferFlowSensitivePointer)
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800686 // Handles comparison between 2 pointers.
Wei Yi Tee217eb5f2022-09-15 03:18:28 -0700687 .CaseOfCFGStmt<BinaryOperator>(isPointerCheckBinOp(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800688 transferFlowSensitiveNullCheckComparison)
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800689 // Handles checking of pointer as boolean.
Wei Yi Tee217eb5f2022-09-15 03:18:28 -0700690 .CaseOfCFGStmt<Expr>(isImplicitCastPointerToBool(),
Dani Ferreira Franco Moura5d2aff42023-01-03 03:42:01 -0800691 transferFlowSensitiveNullCheckImplicitCastPtrToBool)
Wei Yi Tee543af742022-06-01 06:52:24 -0700692 .Build();
693}
694} // namespace
695
696PointerNullabilityAnalysis::PointerNullabilityAnalysis(ASTContext& Context)
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800697 : DataflowAnalysis<PointerNullabilityAnalysis, PointerNullabilityLattice>(
698 Context),
Dani Ferreira Franco Moura97f5c612022-12-17 13:28:24 -0800699 NonFlowSensitiveTransferer(buildNonFlowSensitiveTransferer()),
700 FlowSensitiveTransferer(buildFlowSensitiveTransferer()) {}
Wei Yi Tee543af742022-06-01 06:52:24 -0700701
Sam McCall74bf8642023-06-16 11:21:42 -0700702PointerTypeNullability PointerNullabilityAnalysis::assignNullabilityVariable(
703 const ValueDecl* D, dataflow::Arena& A) {
704 auto [It, Inserted] = NFS.DeclTopLevelNullability.try_emplace(D);
705 if (Inserted) {
706 It->second.Nonnull = &A.create<dataflow::AtomicBoolValue>();
707 It->second.Nullable = &A.create<dataflow::AtomicBoolValue>();
708 }
709 return It->second;
710}
711
Googler9949b462023-02-15 05:09:07 -0800712void PointerNullabilityAnalysis::transfer(const CFGElement& Elt,
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800713 PointerNullabilityLattice& Lattice,
Wei Yi Tee543af742022-06-01 06:52:24 -0700714 Environment& Env) {
Dani Ferreira Franco Moura3d56a222022-11-29 03:12:55 -0800715 TransferState<PointerNullabilityLattice> State(Lattice, Env);
Googler9949b462023-02-15 05:09:07 -0800716 NonFlowSensitiveTransferer(Elt, getASTContext(), State);
717 FlowSensitiveTransferer(Elt, getASTContext(), State);
Wei Yi Tee543af742022-06-01 06:52:24 -0700718}
719
Wei Yi Tee721ee972022-08-11 01:14:54 -0700720BoolValue& mergeBoolValues(BoolValue& Bool1, const Environment& Env1,
721 BoolValue& Bool2, const Environment& Env2,
722 Environment& MergedEnv) {
723 if (&Bool1 == &Bool2) {
724 return Bool1;
725 }
726
727 auto& MergedBool = MergedEnv.makeAtomicBoolValue();
728
729 // If `Bool1` and `Bool2` is constrained to the same true / false value,
730 // `MergedBool` can be constrained similarly without needing to consider the
731 // path taken - this simplifies the flow condition tracked in `MergedEnv`.
732 // Otherwise, information about which path was taken is used to associate
733 // `MergedBool` with `Bool1` and `Bool2`.
734 if (Env1.flowConditionImplies(Bool1) && Env2.flowConditionImplies(Bool2)) {
735 MergedEnv.addToFlowCondition(MergedBool);
736 } else if (Env1.flowConditionImplies(Env1.makeNot(Bool1)) &&
737 Env2.flowConditionImplies(Env2.makeNot(Bool2))) {
738 MergedEnv.addToFlowCondition(MergedEnv.makeNot(MergedBool));
739 } else {
740 // TODO(b/233582219): Flow conditions are not necessarily mutually
Dani Ferreira Franco Moura309f2d72022-11-15 07:09:00 -0800741 // exclusive, a fix is in order: https://reviews.llvm.org/D130270. Update
742 // this section when the patch is commited.
Wei Yi Tee721ee972022-08-11 01:14:54 -0700743 auto& FC1 = Env1.getFlowConditionToken();
744 auto& FC2 = Env2.getFlowConditionToken();
745 MergedEnv.addToFlowCondition(MergedEnv.makeOr(
746 MergedEnv.makeAnd(FC1, MergedEnv.makeIff(MergedBool, Bool1)),
747 MergedEnv.makeAnd(FC2, MergedEnv.makeIff(MergedBool, Bool2))));
748 }
749 return MergedBool;
750}
751
Wei Yi Tee543af742022-06-01 06:52:24 -0700752bool PointerNullabilityAnalysis::merge(QualType Type, const Value& Val1,
753 const Environment& Env1,
754 const Value& Val2,
755 const Environment& Env2,
756 Value& MergedVal,
757 Environment& MergedEnv) {
Wei Yi Tee721ee972022-08-11 01:14:54 -0700758 if (!Type->isAnyPointerType()) {
759 return false;
760 }
761
Martin Brænneed01de62023-06-13 05:45:21 -0700762 if (!hasPointerNullState(cast<PointerValue>(Val1)) ||
763 !hasPointerNullState(cast<PointerValue>(Val2))) {
764 return false;
765 }
766
Googlerf164e032023-05-18 08:38:51 -0700767 auto [Known1, Null1] = getPointerNullState(cast<PointerValue>(Val1));
768 auto [Known2, Null2] = getPointerNullState(cast<PointerValue>(Val2));
Wei Yi Tee721ee972022-08-11 01:14:54 -0700769
770 auto& Known = mergeBoolValues(Known1, Env1, Known2, Env2, MergedEnv);
Dani Ferreira Franco Mouraa0649822022-11-11 07:55:05 -0800771 auto& Null = mergeBoolValues(Null1, Env1, Null2, Env2, MergedEnv);
Wei Yi Tee721ee972022-08-11 01:14:54 -0700772
Dani Ferreira Franco Mouraa0649822022-11-11 07:55:05 -0800773 initPointerNullState(cast<PointerValue>(MergedVal), MergedEnv, &Known, &Null);
Wei Yi Tee721ee972022-08-11 01:14:54 -0700774
775 return true;
Wei Yi Tee543af742022-06-01 06:52:24 -0700776}
Sam McCall5fc2a802023-05-02 05:41:27 -0700777
Wei Yi Tee543af742022-06-01 06:52:24 -0700778} // namespace nullability
779} // namespace tidy
780} // namespace clang