1
$\begingroup$

Python has methods like getattr() which can be used to branch arbitrarily at runtime. As a result, static code analysis tools can't be certain what functions a program will call. A good example comes from Vulture, which is a library that tries to find dead code:

import os class Greeter: def greet(self): print("Hi") def hello_world(): message = "Hello, world!" greeter = Greeter() func_name = "greet" greet_func = getattr(greeter, func_name) greet_func() if __name__ == "__main__": hello_world() 

In the above example, func_name must be evaluated to know where the program would branch.

Are there programming languages that intentionally or unintentionally ensure static analysis tools will always be able to tell where a function will branch? If so, what are some examples?

Secondarily, is there name for this property?

Edit: Per D.W.'s answer, possible branches would include unreachable code and code behind if False:, etc.

$\endgroup$
4
  • $\begingroup$ Can you clarify your edit? What do you mean by "possible branches"? Did you mean to accept D.W.'s answer, or is there something missing from it? $\endgroup$ Commented Sep 23, 2024 at 19:34
  • $\begingroup$ Please don't use "Edit:". Instead, revise the question so it reads well for someone who encounters it for the first time. We want to build up a repository of knowledge that will be useful for others in the future. You don't find "Edit:" in Wikipedia or in an encyclopedia. $\endgroup$ Commented Sep 23, 2024 at 23:52
  • $\begingroup$ if f() then g() requires that f terminates for g to be called. $\endgroup$ Commented Sep 24, 2024 at 9:47
  • $\begingroup$ I think the term you're looking for is early binding $\endgroup$ Commented Oct 24, 2024 at 10:08

1 Answer 1

1
$\begingroup$

Most languages have features that make it undecidable to tell where a function will branch or what function will be invoked by a particular function call. Features that can make this difficult include reflection, function pointers, higher-order functions, self-modifying code, lack of memory safety, and use of eval.

Indeed, even conditional branches can make it hard. Consider this code snippet:

def dispatcher(n): if n==0: f() elsif n==1: g() ... 

It is undecidable whether f is called, because that requires predicting all possible values of n, which is undecidable.

$\endgroup$
1
  • $\begingroup$ Thanks for the reply. I hadn't considered all of those different ways to introduce runtime branching. I think static analysis should include both f() and g() as possibilities. I have made an edit to my question. $\endgroup$ Commented Sep 23, 2024 at 18:51

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.