1 //===-- Transfer.cpp --------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file defines transfer functions that evaluate program statements and
10 //  update an environment accordingly.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Analysis/FlowSensitive/Transfer.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclBase.h"
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/Expr.h"
19 #include "clang/AST/ExprCXX.h"
20 #include "clang/AST/OperationKinds.h"
21 #include "clang/AST/Stmt.h"
22 #include "clang/AST/StmtVisitor.h"
23 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
24 #include "clang/Analysis/FlowSensitive/Value.h"
25 #include "clang/Basic/Builtins.h"
26 #include "clang/Basic/OperatorKinds.h"
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/Support/Casting.h"
29 #include <cassert>
30 #include <memory>
31 #include <tuple>
32 
33 namespace clang {
34 namespace dataflow {
35 
36 static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS,
37                                           Environment &Env) {
38   if (auto *LHSValue =
39           dyn_cast_or_null<BoolValue>(Env.getValue(LHS, SkipPast::Reference)))
40     if (auto *RHSValue =
41             dyn_cast_or_null<BoolValue>(Env.getValue(RHS, SkipPast::Reference)))
42       return Env.makeIff(*LHSValue, *RHSValue);
43 
44   return Env.makeAtomicBoolValue();
45 }
46 
47 class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
48 public:
49   TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env)
50       : StmtToEnv(StmtToEnv), Env(Env) {}
51 
52   void VisitBinaryOperator(const BinaryOperator *S) {
53     const Expr *LHS = S->getLHS();
54     assert(LHS != nullptr);
55 
56     const Expr *RHS = S->getRHS();
57     assert(RHS != nullptr);
58 
59     switch (S->getOpcode()) {
60     case BO_Assign: {
61       auto *LHSLoc = Env.getStorageLocation(*LHS, SkipPast::Reference);
62       if (LHSLoc == nullptr)
63         break;
64 
65       auto *RHSVal = Env.getValue(*RHS, SkipPast::Reference);
66       if (RHSVal == nullptr)
67         break;
68 
69       // Assign a value to the storage location of the left-hand side.
70       Env.setValue(*LHSLoc, *RHSVal);
71 
72       // Assign a storage location for the whole expression.
73       Env.setStorageLocation(*S, *LHSLoc);
74       break;
75     }
76     case BO_LAnd:
77     case BO_LOr: {
78       BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);
79       BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS);
80 
81       auto &Loc = Env.createStorageLocation(*S);
82       Env.setStorageLocation(*S, Loc);
83       if (S->getOpcode() == BO_LAnd)
84         Env.setValue(Loc, Env.makeAnd(LHSVal, RHSVal));
85       else
86         Env.setValue(Loc, Env.makeOr(LHSVal, RHSVal));
87       break;
88     }
89     case BO_NE:
90     case BO_EQ: {
91       auto &LHSEqRHSValue = evaluateBooleanEquality(*LHS, *RHS, Env);
92       auto &Loc = Env.createStorageLocation(*S);
93       Env.setStorageLocation(*S, Loc);
94       Env.setValue(Loc, S->getOpcode() == BO_EQ ? LHSEqRHSValue
95                                                 : Env.makeNot(LHSEqRHSValue));
96       break;
97     }
98     default:
99       break;
100     }
101   }
102 
103   void VisitDeclRefExpr(const DeclRefExpr *S) {
104     assert(S->getDecl() != nullptr);
105     auto *DeclLoc = Env.getStorageLocation(*S->getDecl(), SkipPast::None);
106     if (DeclLoc == nullptr)
107       return;
108 
109     if (S->getDecl()->getType()->isReferenceType()) {
110       Env.setStorageLocation(*S, *DeclLoc);
111     } else {
112       auto &Loc = Env.createStorageLocation(*S);
113       auto &Val = Env.takeOwnership(std::make_unique<ReferenceValue>(*DeclLoc));
114       Env.setStorageLocation(*S, Loc);
115       Env.setValue(Loc, Val);
116     }
117   }
118 
119   void VisitDeclStmt(const DeclStmt *S) {
120     // Group decls are converted into single decls in the CFG so the cast below
121     // is safe.
122     const auto &D = *cast<VarDecl>(S->getSingleDecl());
123 
124     // Static local vars are already initialized in `Environment`.
125     if (D.hasGlobalStorage())
126       return;
127 
128     auto &Loc = Env.createStorageLocation(D);
129     Env.setStorageLocation(D, Loc);
130 
131     const Expr *InitExpr = D.getInit();
132     if (InitExpr == nullptr) {
133       // No initializer expression - associate `Loc` with a new value.
134       if (Value *Val = Env.createValue(D.getType()))
135         Env.setValue(Loc, *Val);
136       return;
137     }
138 
139     InitExpr = D.getInit();
140     assert(InitExpr != nullptr);
141 
142     if (D.getType()->isReferenceType()) {
143       // Initializing a reference variable - do not create a reference to
144       // reference.
145       if (auto *InitExprLoc =
146               Env.getStorageLocation(*InitExpr, SkipPast::Reference)) {
147         auto &Val =
148             Env.takeOwnership(std::make_unique<ReferenceValue>(*InitExprLoc));
149         Env.setValue(Loc, Val);
150         return;
151       }
152     } else if (auto *InitExprVal = Env.getValue(*InitExpr, SkipPast::None)) {
153       Env.setValue(Loc, *InitExprVal);
154       return;
155     }
156 
157     // We arrive here in (the few) cases where an expression is intentionally
158     // "uninterpreted". There are two ways to handle this situation: propagate
159     // the status, so that uninterpreted initializers result in uninterpreted
160     // variables, or provide a default value. We choose the latter so that later
161     // refinements of the variable can be used for reasoning about the
162     // surrounding code.
163     //
164     // FIXME. If and when we interpret all language cases, change this to assert
165     // that `InitExpr` is interpreted, rather than supplying a default value
166     // (assuming we don't update the environment API to return references).
167     if (Value *Val = Env.createValue(D.getType()))
168       Env.setValue(Loc, *Val);
169   }
170 
171   void VisitImplicitCastExpr(const ImplicitCastExpr *S) {
172     const Expr *SubExpr = S->getSubExpr();
173     assert(SubExpr != nullptr);
174 
175     switch (S->getCastKind()) {
176     case CK_IntegralToBoolean: {
177       // This cast creates a new, boolean value from the integral value. We
178       // model that with a fresh value in the environment, unless it's already a
179       // boolean.
180       auto &Loc = Env.createStorageLocation(*S);
181       Env.setStorageLocation(*S, Loc);
182       if (auto *SubExprVal = dyn_cast_or_null<BoolValue>(
183               Env.getValue(*SubExpr, SkipPast::Reference)))
184         Env.setValue(Loc, *SubExprVal);
185       else
186         // FIXME: If integer modeling is added, then update this code to create
187         // the boolean based on the integer model.
188         Env.setValue(Loc, Env.makeAtomicBoolValue());
189       break;
190     }
191 
192     case CK_LValueToRValue: {
193       auto *SubExprVal = Env.getValue(*SubExpr, SkipPast::Reference);
194       if (SubExprVal == nullptr)
195         break;
196 
197       auto &ExprLoc = Env.createStorageLocation(*S);
198       Env.setStorageLocation(*S, ExprLoc);
199       Env.setValue(ExprLoc, *SubExprVal);
200       break;
201     }
202 
203     case CK_IntegralCast:
204       // FIXME: This cast creates a new integral value from the
205       // subexpression. But, because we don't model integers, we don't
206       // distinguish between this new value and the underlying one. If integer
207       // modeling is added, then update this code to create a fresh location and
208       // value.
209     case CK_UncheckedDerivedToBase:
210     case CK_ConstructorConversion:
211     case CK_UserDefinedConversion:
212       // FIXME: Add tests that excercise CK_UncheckedDerivedToBase,
213       // CK_ConstructorConversion, and CK_UserDefinedConversion.
214     case CK_NoOp: {
215       // FIXME: Consider making `Environment::getStorageLocation` skip noop
216       // expressions (this and other similar expressions in the file) instead of
217       // assigning them storage locations.
218       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
219       if (SubExprLoc == nullptr)
220         break;
221 
222       Env.setStorageLocation(*S, *SubExprLoc);
223       break;
224     }
225     default:
226       break;
227     }
228   }
229 
230   void VisitUnaryOperator(const UnaryOperator *S) {
231     const Expr *SubExpr = S->getSubExpr();
232     assert(SubExpr != nullptr);
233 
234     switch (S->getOpcode()) {
235     case UO_Deref: {
236       // Skip past a reference to handle dereference of a dependent pointer.
237       const auto *SubExprVal = cast_or_null<PointerValue>(
238           Env.getValue(*SubExpr, SkipPast::Reference));
239       if (SubExprVal == nullptr)
240         break;
241 
242       auto &Loc = Env.createStorageLocation(*S);
243       Env.setStorageLocation(*S, Loc);
244       Env.setValue(Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(
245                             SubExprVal->getPointeeLoc())));
246       break;
247     }
248     case UO_AddrOf: {
249       // Do not form a pointer to a reference. If `SubExpr` is assigned a
250       // `ReferenceValue` then form a value that points to the location of its
251       // pointee.
252       StorageLocation *PointeeLoc =
253           Env.getStorageLocation(*SubExpr, SkipPast::Reference);
254       if (PointeeLoc == nullptr)
255         break;
256 
257       auto &PointerLoc = Env.createStorageLocation(*S);
258       auto &PointerVal =
259           Env.takeOwnership(std::make_unique<PointerValue>(*PointeeLoc));
260       Env.setStorageLocation(*S, PointerLoc);
261       Env.setValue(PointerLoc, PointerVal);
262       break;
263     }
264     case UO_LNot: {
265       auto *SubExprVal =
266           dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr, SkipPast::None));
267       if (SubExprVal == nullptr)
268         break;
269 
270       auto &ExprLoc = Env.createStorageLocation(*S);
271       Env.setStorageLocation(*S, ExprLoc);
272       Env.setValue(ExprLoc, Env.makeNot(*SubExprVal));
273       break;
274     }
275     default:
276       break;
277     }
278   }
279 
280   void VisitCXXThisExpr(const CXXThisExpr *S) {
281     auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();
282     if (ThisPointeeLoc == nullptr)
283       // Unions are not supported yet, and will not have a location for the
284       // `this` expression's pointee.
285       return;
286 
287     auto &Loc = Env.createStorageLocation(*S);
288     Env.setStorageLocation(*S, Loc);
289     Env.setValue(Loc, Env.takeOwnership(
290                           std::make_unique<PointerValue>(*ThisPointeeLoc)));
291   }
292 
293   void VisitMemberExpr(const MemberExpr *S) {
294     ValueDecl *Member = S->getMemberDecl();
295     assert(Member != nullptr);
296 
297     // FIXME: Consider assigning pointer values to function member expressions.
298     if (Member->isFunctionOrFunctionTemplate())
299       return;
300 
301     if (auto *D = dyn_cast<VarDecl>(Member)) {
302       if (D->hasGlobalStorage()) {
303         auto *VarDeclLoc = Env.getStorageLocation(*D, SkipPast::None);
304         if (VarDeclLoc == nullptr)
305           return;
306 
307         if (VarDeclLoc->getType()->isReferenceType()) {
308           Env.setStorageLocation(*S, *VarDeclLoc);
309         } else {
310           auto &Loc = Env.createStorageLocation(*S);
311           Env.setStorageLocation(*S, Loc);
312           Env.setValue(Loc, Env.takeOwnership(
313                                 std::make_unique<ReferenceValue>(*VarDeclLoc)));
314         }
315         return;
316       }
317     }
318 
319     // The receiver can be either a value or a pointer to a value. Skip past the
320     // indirection to handle both cases.
321     auto *BaseLoc = cast_or_null<AggregateStorageLocation>(
322         Env.getStorageLocation(*S->getBase(), SkipPast::ReferenceThenPointer));
323     if (BaseLoc == nullptr)
324       return;
325 
326     // FIXME: Add support for union types.
327     if (BaseLoc->getType()->isUnionType())
328       return;
329 
330     auto &MemberLoc = BaseLoc->getChild(*Member);
331     if (MemberLoc.getType()->isReferenceType()) {
332       Env.setStorageLocation(*S, MemberLoc);
333     } else {
334       auto &Loc = Env.createStorageLocation(*S);
335       Env.setStorageLocation(*S, Loc);
336       Env.setValue(
337           Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(MemberLoc)));
338     }
339   }
340 
341   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
342     const Expr *InitExpr = S->getExpr();
343     assert(InitExpr != nullptr);
344 
345     Value *InitExprVal = Env.getValue(*InitExpr, SkipPast::None);
346     if (InitExprVal == nullptr)
347       return;
348 
349     const FieldDecl *Field = S->getField();
350     assert(Field != nullptr);
351 
352     auto &ThisLoc =
353         *cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
354     auto &FieldLoc = ThisLoc.getChild(*Field);
355     Env.setValue(FieldLoc, *InitExprVal);
356   }
357 
358   void VisitCXXConstructExpr(const CXXConstructExpr *S) {
359     const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
360     assert(ConstructorDecl != nullptr);
361 
362     if (ConstructorDecl->isCopyOrMoveConstructor()) {
363       assert(S->getNumArgs() == 1);
364 
365       const Expr *Arg = S->getArg(0);
366       assert(Arg != nullptr);
367 
368       if (S->isElidable()) {
369         auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
370         if (ArgLoc == nullptr)
371           return;
372 
373         Env.setStorageLocation(*S, *ArgLoc);
374       } else if (auto *ArgVal = Env.getValue(*Arg, SkipPast::Reference)) {
375         auto &Loc = Env.createStorageLocation(*S);
376         Env.setStorageLocation(*S, Loc);
377         Env.setValue(Loc, *ArgVal);
378       }
379       return;
380     }
381 
382     auto &Loc = Env.createStorageLocation(*S);
383     Env.setStorageLocation(*S, Loc);
384     if (Value *Val = Env.createValue(S->getType()))
385       Env.setValue(Loc, *Val);
386   }
387 
388   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
389     if (S->getOperator() == OO_Equal) {
390       assert(S->getNumArgs() == 2);
391 
392       const Expr *Arg0 = S->getArg(0);
393       assert(Arg0 != nullptr);
394 
395       const Expr *Arg1 = S->getArg(1);
396       assert(Arg1 != nullptr);
397 
398       // Evaluate only copy and move assignment operators.
399       auto *Arg0Type = Arg0->getType()->getUnqualifiedDesugaredType();
400       auto *Arg1Type = Arg1->getType()->getUnqualifiedDesugaredType();
401       if (Arg0Type != Arg1Type)
402         return;
403 
404       auto *ObjectLoc = Env.getStorageLocation(*Arg0, SkipPast::Reference);
405       if (ObjectLoc == nullptr)
406         return;
407 
408       auto *Val = Env.getValue(*Arg1, SkipPast::Reference);
409       if (Val == nullptr)
410         return;
411 
412       // Assign a value to the storage location of the object.
413       Env.setValue(*ObjectLoc, *Val);
414 
415       // FIXME: Add a test for the value of the whole expression.
416       // Assign a storage location for the whole expression.
417       Env.setStorageLocation(*S, *ObjectLoc);
418     }
419   }
420 
421   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
422     if (S->getCastKind() == CK_ConstructorConversion) {
423       const Expr *SubExpr = S->getSubExpr();
424       assert(SubExpr != nullptr);
425 
426       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
427       if (SubExprLoc == nullptr)
428         return;
429 
430       Env.setStorageLocation(*S, *SubExprLoc);
431     }
432   }
433 
434   void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
435     auto &Loc = Env.createStorageLocation(*S);
436     Env.setStorageLocation(*S, Loc);
437     if (Value *Val = Env.createValue(S->getType()))
438       Env.setValue(Loc, *Val);
439   }
440 
441   void VisitCallExpr(const CallExpr *S) {
442     // Of clang's builtins, only `__builtin_expect` is handled explicitly, since
443     // others (like trap, debugtrap, and unreachable) are handled by CFG
444     // construction.
445     if (S->isCallToStdMove()) {
446       assert(S->getNumArgs() == 1);
447 
448       const Expr *Arg = S->getArg(0);
449       assert(Arg != nullptr);
450 
451       auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::None);
452       if (ArgLoc == nullptr)
453         return;
454 
455       Env.setStorageLocation(*S, *ArgLoc);
456     } else if (S->getDirectCallee() != nullptr &&
457                S->getDirectCallee()->getBuiltinID() ==
458                    Builtin::BI__builtin_expect) {
459       assert(S->getNumArgs() > 0);
460       assert(S->getArg(0) != nullptr);
461       // `__builtin_expect` returns by-value, so strip away any potential
462       // references in the argument.
463       auto *ArgLoc = Env.getStorageLocation(*S->getArg(0), SkipPast::Reference);
464       if (ArgLoc == nullptr)
465         return;
466       Env.setStorageLocation(*S, *ArgLoc);
467     }
468   }
469 
470   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
471     const Expr *SubExpr = S->getSubExpr();
472     assert(SubExpr != nullptr);
473 
474     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
475     if (SubExprLoc == nullptr)
476       return;
477 
478     Env.setStorageLocation(*S, *SubExprLoc);
479   }
480 
481   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
482     const Expr *SubExpr = S->getSubExpr();
483     assert(SubExpr != nullptr);
484 
485     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
486     if (SubExprLoc == nullptr)
487       return;
488 
489     Env.setStorageLocation(*S, *SubExprLoc);
490   }
491 
492   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
493     if (S->getCastKind() == CK_NoOp) {
494       const Expr *SubExpr = S->getSubExpr();
495       assert(SubExpr != nullptr);
496 
497       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
498       if (SubExprLoc == nullptr)
499         return;
500 
501       Env.setStorageLocation(*S, *SubExprLoc);
502     }
503   }
504 
505   void VisitConditionalOperator(const ConditionalOperator *S) {
506     // FIXME: Revisit this once flow conditions are added to the framework. For
507     // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
508     // condition.
509     auto &Loc = Env.createStorageLocation(*S);
510     Env.setStorageLocation(*S, Loc);
511     if (Value *Val = Env.createValue(S->getType()))
512       Env.setValue(Loc, *Val);
513   }
514 
515   void VisitInitListExpr(const InitListExpr *S) {
516     QualType Type = S->getType();
517 
518     auto &Loc = Env.createStorageLocation(*S);
519     Env.setStorageLocation(*S, Loc);
520 
521     auto *Val = Env.createValue(Type);
522     if (Val == nullptr)
523       return;
524 
525     Env.setValue(Loc, *Val);
526 
527     if (Type->isStructureOrClassType()) {
528       for (auto IT : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) {
529         const FieldDecl *Field = std::get<0>(IT);
530         assert(Field != nullptr);
531 
532         const Expr *Init = std::get<1>(IT);
533         assert(Init != nullptr);
534 
535         if (Value *InitVal = Env.getValue(*Init, SkipPast::None))
536           cast<StructValue>(Val)->setChild(*Field, *InitVal);
537       }
538     }
539     // FIXME: Implement array initialization.
540   }
541 
542   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
543     auto &Loc = Env.createStorageLocation(*S);
544     Env.setStorageLocation(*S, Loc);
545     Env.setValue(Loc, Env.getBoolLiteralValue(S->getValue()));
546   }
547 
548   void VisitParenExpr(const ParenExpr *S) {
549     // The CFG does not contain `ParenExpr` as top-level statements in basic
550     // blocks, however manual traversal to sub-expressions may encounter them.
551     // Redirect to the sub-expression.
552     auto *SubExpr = S->getSubExpr();
553     assert(SubExpr != nullptr);
554     Visit(SubExpr);
555   }
556 
557   void VisitExprWithCleanups(const ExprWithCleanups *S) {
558     // The CFG does not contain `ExprWithCleanups` as top-level statements in
559     // basic blocks, however manual traversal to sub-expressions may encounter
560     // them. Redirect to the sub-expression.
561     auto *SubExpr = S->getSubExpr();
562     assert(SubExpr != nullptr);
563     Visit(SubExpr);
564   }
565 
566 private:
567   BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) {
568     // `SubExpr` and its parent logic operator might be part of different basic
569     // blocks. We try to access the value that is assigned to `SubExpr` in the
570     // corresponding environment.
571     if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr)) {
572       if (auto *Val = dyn_cast_or_null<BoolValue>(
573               SubExprEnv->getValue(SubExpr, SkipPast::Reference)))
574         return *Val;
575     }
576 
577     if (Env.getStorageLocation(SubExpr, SkipPast::None) == nullptr) {
578       // Sub-expressions that are logic operators are not added in basic blocks
579       // (e.g. see CFG for `bool d = a && (b || c);`). If `SubExpr` is a logic
580       // operator, it may not have been evaluated and assigned a value yet. In
581       // that case, we need to first visit `SubExpr` and then try to get the
582       // value that gets assigned to it.
583       Visit(&SubExpr);
584     }
585 
586     if (auto *Val = dyn_cast_or_null<BoolValue>(
587             Env.getValue(SubExpr, SkipPast::Reference)))
588       return *Val;
589 
590     // If the value of `SubExpr` is still unknown, we create a fresh symbolic
591     // boolean value for it.
592     return Env.makeAtomicBoolValue();
593   }
594 
595   const StmtToEnvMap &StmtToEnv;
596   Environment &Env;
597 };
598 
599 void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
600   TransferVisitor(StmtToEnv, Env).Visit(&S);
601 }
602 
603 } // namespace dataflow
604 } // namespace clang
605