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