 Hi, and welcome back to the program analysis course. This is the sixth and last video of the lecture on data flow analysis. And what I want to do in this last short video is to talk about the sensitivities that aesthetic analysis may have. This is a question that is not strictly related to data flow analysis, but it's a very good point in time during this course to talk about these sensitivities. Because you now have a good understanding of what aesthetic analysis can do and maybe also cannot do, and that's a good point to understand what these sensitivities are. So what sensitivities are describing is what kind of properties of your program aesthetic analysis is really looking at. Because aesthetic analysis is only looking at a source code, but not really executing the program, it needs to abstract away a few things. So in principle, it does not have to do this, but if it considers everything, then it's basically executing the program with all possible paths and emulating all possible behaviors. So in order to be practical, most aesthetic analysis instead abstract away a few things. And what these sensitivities are describing is what kinds of properties of the code are considered and what kinds of properties are ignored. So let me just introduce three terms that come up pretty often. The first of them is that an analysis is flow sensitive. So flow sensitive simply means that the analysis takes into account the order of statements, whereas a flow insensitive analysis may look at the statements that exist, for example, within the function, but doesn't really reason about the order in which these statements are executed. Another kind of sensitivity is about path. So an analysis is path sensitive. If it takes into account the predicates that are checked at conditional branches. So if an analysis is path sensitive, and if there is some if with some condition, then the analysis will know that the condition is true in the then branch, but falls in the else branch. Whereas a path insensitive analysis just knows that there are two paths, but it doesn't really know whether the condition is true or false on any of them. And then a third kind of sensitivity that is important is context sensitivity, which only matters for an interprocedural analysis. So what happens here is that analysis that is context sensitive takes into account the specific call side that leads to another function. So if a function is called in, say, two places in your program, then in one place where it's called, so on one call side, the analysis may find different behavior in this function than when it's called from the other call side. Whereas a context insensitive static analysis does not distinguish these call sides, so no matter where a function is called, it will be always analyzed the same way. So let me illustrate these terms with very simple examples and let's start with this flow sensitivity term. So let's say we have a piece of code that looks like this. We have an if with some condition that doesn't really matter here. And then we have three assignments, one that is writing the value of three into x and then one that writes five into x. And now the question that you may ask aesthetic analysis is at this point in time, so basically after having executed or when reaching the end of this branch of DF, what is the value of x? And now depending on whether the analysis is flow sensitive or flow insensitive, it will give you a different answer. So if your analysis is flow sensitive, so if it does look at the order in which statements are executed, then it will see that first you assign three and then you override this value and assign five and therefore the value of x must be five. In contrast, a flow insensitive analysis doesn't really reason about the order in which these two statements happen. And as a result, what the analysis will tell you, well, it could be three or five. Now you may look at this small example and wonder why someone would implement a flow insensitive analysis, but in practice it can actually save quite some time because you do not have to reason about all the different statements in the order in which they happen, but you just merge them into a set of statements and analyze all of them together. Next let's have a look at an example for path sensitivity, which will be slightly more complex than before but still just a small piece of code. So we start with some assignment of zero to variable x and then we have a conditional that checks whether a is larger than zero and if it is, we are assigning one to x and otherwise we are assigning two to x. And then after this if, we are having another if, which again is checking if a is larger than zero and if it is, we are assigning x the old value of x plus three and this is all the code does. And now the question that we are asking aesthetic analysis is whether here at the very end of this code x can have the value of five. So now depending on whether the analysis is path sensitive, it'll give you the answer yes or no. So if the analysis is path sensitive, so if it basically keeps track of the conditions that hold in branches, then it's going to figure out that if the condition a greater than zero is true, x will be one. So we are going to execute this branch here. And then if we add three to this, the value will be four. So it's not equal to five. In contrast, if the analysis is path insensitive, it's going to say yes. And the reason is simply that for the first if it's considering two branches, one where x will be one and the other one where x will be two. And then again for the second if it's going to consider two branches, one where we take the branch and assign three more to x and the other one where we don't do this. And now it doesn't really know which of these branches can be combined or cannot be combined. So it will consider the case where x is initially assigned two. And then we add three to it, which means that x could be five according to the analysis and it will return yes. So path sensitivity basically determines whether an analysis is able to reason about the outcome of different conditionals across the different branches. Finally let's have a look at an example for context sensitivity. So in that example, we're going to have a global variable called n which initially is one. And then we have two functions, one function called f in which we are checking some variable x. And if this is true, then we are calling another function g with argument three. And if this is not true, then we are assigning some other value to n which is three and then call function g with argument five. And then the second function is that function g that we have been calling here in which we call the argument y. And now the question we are asking our static analysis is whether here inside function g the value of n can be equal to the value of y. And now depending on whether your analysis is context insensitive or context sensitive, you'll get a different answer. So if the analysis is context insensitive, then it's going to conflate all the call sites of g into just one global call site. And in this case, it will see that sometimes n can be three and sometimes g is called with three as the argument and therefore n can be equal to y within function g. So it's going to say yes. And the reason is that it's conflating all call sites of the function g. And in contrast, if your analysis is context sensitive, which means that it's going to distinguish between different call sites of g and is propagating different kinds of states into the analysis of function g depending on where g is called, then it's going to say no, because it sees that at this one call site, the one here, g is called with three. So y will be three, but n is not three. And that here at the other call site, n is three, but y will be five. So again, these two values are not the same. Now as a little quiz to test whether you've understood these terms of flow sensitivity, and context sensitivity, let's consider an intra-procedural data flow analysis and more specifically one that we've seen earlier, which was this live variables analysis. And the question for you is which of these sensitivities does this analysis actually have? So now I invite you here to stop the video and then think about it yourself. And then once you've hopefully done this, let me show you the solution. So such a live variables analysis is flow sensitive. And the answer is yes, because basically every data flow analysis is flow sensitive because it's looking at the statements in exactly the order in which they are happening according to the source code because it's based on a control flow graph where the statements happen in a specific order. In contrast, the live variables analysis is not path sensitive because it does not track the predicates that evaluate to either true or false at a conditional. So it doesn't really know whether you are going to take this branch or that branch. And if you have the same conditional in multiple ifs, then it doesn't really know which of the branches can be combined with each other. And then the question whether the analysis is context sensitive isn't really relevant for an intra-procedural data flow analysis simply because it reasons only about one function at a time. So we cannot really answer that question because it isn't relevant. All right. And that's the very end of the data flow lecture. I hope you now have a good understanding of this very popular way of formulating static analysis, which allows you to formulate many, many different kinds of static analyses in a single framework by basically defining these six properties of data flow analysis that we've seen in the lecture. Thank you very much for listening and see you next time.