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     assert(ThisPointeeLoc != nullptr);
283 
284     auto &Loc = Env.createStorageLocation(*S);
285     Env.setStorageLocation(*S, Loc);
286     Env.setValue(Loc, Env.takeOwnership(
287                           std::make_unique<PointerValue>(*ThisPointeeLoc)));
288   }
289 
290   void VisitMemberExpr(const MemberExpr *S) {
291     ValueDecl *Member = S->getMemberDecl();
292     assert(Member != nullptr);
293 
294     // FIXME: Consider assigning pointer values to function member expressions.
295     if (Member->isFunctionOrFunctionTemplate())
296       return;
297 
298     if (auto *D = dyn_cast<VarDecl>(Member)) {
299       if (D->hasGlobalStorage()) {
300         auto *VarDeclLoc = Env.getStorageLocation(*D, SkipPast::None);
301         if (VarDeclLoc == nullptr)
302           return;
303 
304         if (VarDeclLoc->getType()->isReferenceType()) {
305           Env.setStorageLocation(*S, *VarDeclLoc);
306         } else {
307           auto &Loc = Env.createStorageLocation(*S);
308           Env.setStorageLocation(*S, Loc);
309           Env.setValue(Loc, Env.takeOwnership(
310                                 std::make_unique<ReferenceValue>(*VarDeclLoc)));
311         }
312         return;
313       }
314     }
315 
316     // The receiver can be either a value or a pointer to a value. Skip past the
317     // indirection to handle both cases.
318     auto *BaseLoc = cast_or_null<AggregateStorageLocation>(
319         Env.getStorageLocation(*S->getBase(), SkipPast::ReferenceThenPointer));
320     if (BaseLoc == nullptr)
321       return;
322 
323     // FIXME: Add support for union types.
324     if (BaseLoc->getType()->isUnionType())
325       return;
326 
327     auto &MemberLoc = BaseLoc->getChild(*Member);
328     if (MemberLoc.getType()->isReferenceType()) {
329       Env.setStorageLocation(*S, MemberLoc);
330     } else {
331       auto &Loc = Env.createStorageLocation(*S);
332       Env.setStorageLocation(*S, Loc);
333       Env.setValue(
334           Loc, Env.takeOwnership(std::make_unique<ReferenceValue>(MemberLoc)));
335     }
336   }
337 
338   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
339     const Expr *InitExpr = S->getExpr();
340     assert(InitExpr != nullptr);
341 
342     Value *InitExprVal = Env.getValue(*InitExpr, SkipPast::None);
343     if (InitExprVal == nullptr)
344       return;
345 
346     const FieldDecl *Field = S->getField();
347     assert(Field != nullptr);
348 
349     auto &ThisLoc =
350         *cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
351     auto &FieldLoc = ThisLoc.getChild(*Field);
352     Env.setValue(FieldLoc, *InitExprVal);
353   }
354 
355   void VisitCXXConstructExpr(const CXXConstructExpr *S) {
356     const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
357     assert(ConstructorDecl != nullptr);
358 
359     if (ConstructorDecl->isCopyOrMoveConstructor()) {
360       assert(S->getNumArgs() == 1);
361 
362       const Expr *Arg = S->getArg(0);
363       assert(Arg != nullptr);
364 
365       if (S->isElidable()) {
366         auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::Reference);
367         if (ArgLoc == nullptr)
368           return;
369 
370         Env.setStorageLocation(*S, *ArgLoc);
371       } else if (auto *ArgVal = Env.getValue(*Arg, SkipPast::Reference)) {
372         auto &Loc = Env.createStorageLocation(*S);
373         Env.setStorageLocation(*S, Loc);
374         Env.setValue(Loc, *ArgVal);
375       }
376       return;
377     }
378 
379     auto &Loc = Env.createStorageLocation(*S);
380     Env.setStorageLocation(*S, Loc);
381     if (Value *Val = Env.createValue(S->getType()))
382       Env.setValue(Loc, *Val);
383   }
384 
385   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
386     if (S->getOperator() == OO_Equal) {
387       assert(S->getNumArgs() == 2);
388 
389       const Expr *Arg0 = S->getArg(0);
390       assert(Arg0 != nullptr);
391 
392       const Expr *Arg1 = S->getArg(1);
393       assert(Arg1 != nullptr);
394 
395       // Evaluate only copy and move assignment operators.
396       auto *Arg0Type = Arg0->getType()->getUnqualifiedDesugaredType();
397       auto *Arg1Type = Arg1->getType()->getUnqualifiedDesugaredType();
398       if (Arg0Type != Arg1Type)
399         return;
400 
401       auto *ObjectLoc = Env.getStorageLocation(*Arg0, SkipPast::Reference);
402       if (ObjectLoc == nullptr)
403         return;
404 
405       auto *Val = Env.getValue(*Arg1, SkipPast::Reference);
406       if (Val == nullptr)
407         return;
408 
409       // Assign a value to the storage location of the object.
410       Env.setValue(*ObjectLoc, *Val);
411 
412       // FIXME: Add a test for the value of the whole expression.
413       // Assign a storage location for the whole expression.
414       Env.setStorageLocation(*S, *ObjectLoc);
415     }
416   }
417 
418   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) {
419     if (S->getCastKind() == CK_ConstructorConversion) {
420       const Expr *SubExpr = S->getSubExpr();
421       assert(SubExpr != nullptr);
422 
423       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
424       if (SubExprLoc == nullptr)
425         return;
426 
427       Env.setStorageLocation(*S, *SubExprLoc);
428     }
429   }
430 
431   void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
432     auto &Loc = Env.createStorageLocation(*S);
433     Env.setStorageLocation(*S, Loc);
434     if (Value *Val = Env.createValue(S->getType()))
435       Env.setValue(Loc, *Val);
436   }
437 
438   void VisitCallExpr(const CallExpr *S) {
439     // Of clang's builtins, only `__builtin_expect` is handled explicitly, since
440     // others (like trap, debugtrap, and unreachable) are handled by CFG
441     // construction.
442     if (S->isCallToStdMove()) {
443       assert(S->getNumArgs() == 1);
444 
445       const Expr *Arg = S->getArg(0);
446       assert(Arg != nullptr);
447 
448       auto *ArgLoc = Env.getStorageLocation(*Arg, SkipPast::None);
449       if (ArgLoc == nullptr)
450         return;
451 
452       Env.setStorageLocation(*S, *ArgLoc);
453     } else if (S->getDirectCallee() != nullptr &&
454                S->getDirectCallee()->getBuiltinID() ==
455                    Builtin::BI__builtin_expect) {
456       assert(S->getNumArgs() > 0);
457       assert(S->getArg(0) != nullptr);
458       // `__builtin_expect` returns by-value, so strip away any potential
459       // references in the argument.
460       auto *ArgLoc = Env.getStorageLocation(*S->getArg(0), SkipPast::Reference);
461       if (ArgLoc == nullptr)
462         return;
463       Env.setStorageLocation(*S, *ArgLoc);
464     }
465   }
466 
467   void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
468     const Expr *SubExpr = S->getSubExpr();
469     assert(SubExpr != nullptr);
470 
471     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
472     if (SubExprLoc == nullptr)
473       return;
474 
475     Env.setStorageLocation(*S, *SubExprLoc);
476   }
477 
478   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
479     const Expr *SubExpr = S->getSubExpr();
480     assert(SubExpr != nullptr);
481 
482     auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
483     if (SubExprLoc == nullptr)
484       return;
485 
486     Env.setStorageLocation(*S, *SubExprLoc);
487   }
488 
489   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
490     if (S->getCastKind() == CK_NoOp) {
491       const Expr *SubExpr = S->getSubExpr();
492       assert(SubExpr != nullptr);
493 
494       auto *SubExprLoc = Env.getStorageLocation(*SubExpr, SkipPast::None);
495       if (SubExprLoc == nullptr)
496         return;
497 
498       Env.setStorageLocation(*S, *SubExprLoc);
499     }
500   }
501 
502   void VisitConditionalOperator(const ConditionalOperator *S) {
503     // FIXME: Revisit this once flow conditions are added to the framework. For
504     // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
505     // condition.
506     auto &Loc = Env.createStorageLocation(*S);
507     Env.setStorageLocation(*S, Loc);
508     if (Value *Val = Env.createValue(S->getType()))
509       Env.setValue(Loc, *Val);
510   }
511 
512   void VisitInitListExpr(const InitListExpr *S) {
513     QualType Type = S->getType();
514 
515     auto &Loc = Env.createStorageLocation(*S);
516     Env.setStorageLocation(*S, Loc);
517 
518     auto *Val = Env.createValue(Type);
519     if (Val == nullptr)
520       return;
521 
522     Env.setValue(Loc, *Val);
523 
524     if (Type->isStructureOrClassType()) {
525       for (auto IT : llvm::zip(Type->getAsRecordDecl()->fields(), S->inits())) {
526         const FieldDecl *Field = std::get<0>(IT);
527         assert(Field != nullptr);
528 
529         const Expr *Init = std::get<1>(IT);
530         assert(Init != nullptr);
531 
532         if (Value *InitVal = Env.getValue(*Init, SkipPast::None))
533           cast<StructValue>(Val)->setChild(*Field, *InitVal);
534       }
535     }
536     // FIXME: Implement array initialization.
537   }
538 
539   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
540     auto &Loc = Env.createStorageLocation(*S);
541     Env.setStorageLocation(*S, Loc);
542     Env.setValue(Loc, Env.getBoolLiteralValue(S->getValue()));
543   }
544 
545   void VisitParenExpr(const ParenExpr *S) {
546     // The CFG does not contain `ParenExpr` as top-level statements in basic
547     // blocks, however manual traversal to sub-expressions may encounter them.
548     // Redirect to the sub-expression.
549     auto *SubExpr = S->getSubExpr();
550     assert(SubExpr != nullptr);
551     Visit(SubExpr);
552   }
553 
554   void VisitExprWithCleanups(const ExprWithCleanups *S) {
555     // The CFG does not contain `ExprWithCleanups` as top-level statements in
556     // basic blocks, however manual traversal to sub-expressions may encounter
557     // them. Redirect to the sub-expression.
558     auto *SubExpr = S->getSubExpr();
559     assert(SubExpr != nullptr);
560     Visit(SubExpr);
561   }
562 
563 private:
564   BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) {
565     // `SubExpr` and its parent logic operator might be part of different basic
566     // blocks. We try to access the value that is assigned to `SubExpr` in the
567     // corresponding environment.
568     if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr)) {
569       if (auto *Val = dyn_cast_or_null<BoolValue>(
570               SubExprEnv->getValue(SubExpr, SkipPast::Reference)))
571         return *Val;
572     }
573 
574     // Sub-expressions that are logic operators are not added in basic blocks
575     // (e.g. see CFG for `bool d = a && (b || c);`). If `SubExpr` is a logic
576     // operator, it isn't evaluated and assigned a value yet. In that case, we
577     // need to first visit `SubExpr` and then try to get the value that gets
578     // assigned to it.
579     Visit(&SubExpr);
580     if (auto *Val = dyn_cast_or_null<BoolValue>(
581             Env.getValue(SubExpr, SkipPast::Reference)))
582       return *Val;
583 
584     // If the value of `SubExpr` is still unknown, we create a fresh symbolic
585     // boolean value for it.
586     return Env.makeAtomicBoolValue();
587   }
588 
589   const StmtToEnvMap &StmtToEnv;
590   Environment &Env;
591 };
592 
593 void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
594   TransferVisitor(StmtToEnv, Env).Visit(&S);
595 }
596 
597 } // namespace dataflow
598 } // namespace clang
599