ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
nested_func_transform.cpp File Reference
#include <clang-c-frontend/nested_func_transform.h>
#include <util/base/compiler_defs.h>
#include <clang/Basic/Diagnostic.h>
#include <clang/Basic/DiagnosticOptions.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/LangOptions.h>
#include <clang/Basic/SourceManager.h>
#include <clang/Basic/TokenKinds.h>
#include <clang/Basic/Version.inc>
#include <clang/Lex/Lexer.h>
#include <clang/Lex/Token.h>
#include <llvm/ADT/IntrusiveRefCntPtr.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/MemoryBuffer.h>
#include <util/message/message.h>
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdio>
#include <fstream>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
Include dependency graph for nested_func_transform.cpp:

Classes

struct  local_var
struct  nested_func
struct  token
struct  pp_range
struct  scope_walker
struct  rewrite_op

Enumerations

enum class  tok_kind {
  identifier , punctuation , number , string_lit ,
  char_lit , pp_directive , whitespace , eof
}

Functions

static std::vector< pp_range > scan_pp_directives (const std::string &src)
static tok_kind map_clang_kind (const clang::Token &t)
static std::string spelling_of (const clang::Token &t, const clang::SourceManager &sm, const clang::LangOptions &lo)
static std::vector< token > tokenize (const std::string &src)
static size_t skip_ws (const std::vector< token > &toks, size_t idx)
static const std::set< std::string > & type_keywords ()
static bool is_type_keyword (const std::string &s)
static bool is_non_func_keyword (const std::string &s)
static bool try_parse_func_def (const std::vector< token > &toks, size_t idx, const std::string &enclosing_name, nested_func &out, size_t &def_end_tok_idx, const std::string &src)
static size_t parse_decl_at (const std::vector< token > &toks, size_t idx, size_t end, const std::set< std::string > &nested_func_names, std::vector< local_var > &out_vars)
static std::vector< local_var > collect_local_vars (const std::vector< token > &toks, size_t body_start_tok, size_t body_end_tok, const std::set< std::string > &nested_func_names)
static std::vector< local_var > collect_params (const std::string &params_text)
static bool check_fptr_use (const std::vector< token > &toks, size_t body_start_tok, size_t body_end_tok, size_t def_start_tok, size_t def_end_tok, const std::string &func_name)
static size_t skip_ws_back (const std::vector< token > &toks, size_t idx, size_t begin)
static size_t find_control_stmt_end (const std::vector< token > &toks, size_t idx, size_t end)
template<class OnUse>
static void scope_walk (scope_walker &w, OnUse on_use)
static std::vector< local_var > find_captures (const std::string &body_text, const std::vector< local_var > &enclosing_vars, const std::string &params_text)
static std::string lifted_name (const std::string &enclosing, const std::string &nested)
static std::string capture_global_name (const std::string &enclosing, const std::string &nested, const std::string &var)
static std::string capture_param_name (const std::string &enclosing, const std::string &nested, const std::string &var)
static std::string rewrite_identifiers (const std::string &text, const std::map< std::string, std::string > &replacements, const std::set< std::string > *scope_aware_names=nullptr, std::set< std::string > seed_scope={})
static std::map< std::string, std::string > build_capture_replacements (const std::vector< local_var > &captures, bool fptr_mode, const std::string &enclosing, const std::string &func_name)
static std::string rewrite_body (const std::string &body_text, const std::string &params_text, const std::vector< local_var > &captures, bool fptr_mode, const std::string &enclosing, const std::string &func_name)
static std::string inner_params (const std::string &params_text)
static std::set< std::string > find_sibling_callees (const std::string &body_text, const std::string &params_text, const std::set< std::string > &sibling_names)
static void compute_effective_captures (std::vector< nested_func > &nested, const std::map< std::string, std::vector< local_var > > &enc_vars_by_name)
static std::vector< nested_func > find_nested_functions (const std::string &src, const std::vector< token > &toks)
static std::string apply_rewrites (std::string s, std::vector< rewrite_op > ops)
static std::vector< rewrite_op > plan_nested_call_rewrites (const std::vector< token > &body_toks, size_t tok_begin, size_t tok_end, const std::vector< const nested_func * > &siblings, const std::function< std::string(const std::string &)> &source_for)
static std::string rewrite_nested_calls (const std::string &body, const std::vector< const nested_func * > &siblings, const std::function< std::string(const std::string &)> &source_for)
static std::string transform_one_pass (const std::string &src)
static std::string usr_stem (const std::string &source_path)
 The source's basename, reduced to characters that read cleanly inside a symbol id.
std::optional< file_operations::tmp_file > transform_nested_functions (const std::string &source_path)
 Transforms GCC nested function definitions in a C source file into standard C by lambda-lifting them to file scope.

Enumeration Type Documentation

◆ tok_kind

enum class tok_kind
strong
Enumerator
identifier 
punctuation 
number 
string_lit 
char_lit 
pp_directive 
whitespace 
eof 

Function Documentation

◆ apply_rewrites()

std::string apply_rewrites ( std::string s,
std::vector< rewrite_op > ops )
static

◆ build_capture_replacements()

std::map< std::string, std::string > build_capture_replacements ( const std::vector< local_var > & captures,
bool fptr_mode,
const std::string & enclosing,
const std::string & func_name )
static

◆ capture_global_name()

std::string capture_global_name ( const std::string & enclosing,
const std::string & nested,
const std::string & var )
static

◆ capture_param_name()

std::string capture_param_name ( const std::string & enclosing,
const std::string & nested,
const std::string & var )
static

◆ check_fptr_use()

bool check_fptr_use ( const std::vector< token > & toks,
size_t body_start_tok,
size_t body_end_tok,
size_t def_start_tok,
size_t def_end_tok,
const std::string & func_name )
static

◆ collect_local_vars()

std::vector< local_var > collect_local_vars ( const std::vector< token > & toks,
size_t body_start_tok,
size_t body_end_tok,
const std::set< std::string > & nested_func_names )
static

◆ collect_params()

std::vector< local_var > collect_params ( const std::string & params_text)
static

◆ compute_effective_captures()

void compute_effective_captures ( std::vector< nested_func > & nested,
const std::map< std::string, std::vector< local_var > > & enc_vars_by_name )
static

◆ find_captures()

std::vector< local_var > find_captures ( const std::string & body_text,
const std::vector< local_var > & enclosing_vars,
const std::string & params_text )
static

◆ find_control_stmt_end()

size_t find_control_stmt_end ( const std::vector< token > & toks,
size_t idx,
size_t end )
static

◆ find_nested_functions()

std::vector< nested_func > find_nested_functions ( const std::string & src,
const std::vector< token > & toks )
static

◆ find_sibling_callees()

std::set< std::string > find_sibling_callees ( const std::string & body_text,
const std::string & params_text,
const std::set< std::string > & sibling_names )
static

◆ inner_params()

std::string inner_params ( const std::string & params_text)
static

◆ is_non_func_keyword()

bool is_non_func_keyword ( const std::string & s)
static

◆ is_type_keyword()

bool is_type_keyword ( const std::string & s)
static

◆ lifted_name()

std::string lifted_name ( const std::string & enclosing,
const std::string & nested )
static

◆ map_clang_kind()

tok_kind map_clang_kind ( const clang::Token & t)
static

◆ parse_decl_at()

size_t parse_decl_at ( const std::vector< token > & toks,
size_t idx,
size_t end,
const std::set< std::string > & nested_func_names,
std::vector< local_var > & out_vars )
static

◆ plan_nested_call_rewrites()

std::vector< rewrite_op > plan_nested_call_rewrites ( const std::vector< token > & body_toks,
size_t tok_begin,
size_t tok_end,
const std::vector< const nested_func * > & siblings,
const std::function< std::string(const std::string &)> & source_for )
static

◆ rewrite_body()

std::string rewrite_body ( const std::string & body_text,
const std::string & params_text,
const std::vector< local_var > & captures,
bool fptr_mode,
const std::string & enclosing,
const std::string & func_name )
static

◆ rewrite_identifiers()

std::string rewrite_identifiers ( const std::string & text,
const std::map< std::string, std::string > & replacements,
const std::set< std::string > * scope_aware_names = nullptr,
std::set< std::string > seed_scope = {} )
static

◆ rewrite_nested_calls()

std::string rewrite_nested_calls ( const std::string & body,
const std::vector< const nested_func * > & siblings,
const std::function< std::string(const std::string &)> & source_for )
static

◆ scan_pp_directives()

std::vector< pp_range > scan_pp_directives ( const std::string & src)
static

◆ scope_walk()

template<class OnUse>
void scope_walk ( scope_walker & w,
OnUse on_use )
static

◆ skip_ws()

size_t skip_ws ( const std::vector< token > & toks,
size_t idx )
static

◆ skip_ws_back()

size_t skip_ws_back ( const std::vector< token > & toks,
size_t idx,
size_t begin )
static

◆ spelling_of()

std::string spelling_of ( const clang::Token & t,
const clang::SourceManager & sm,
const clang::LangOptions & lo )
static

◆ tokenize()

std::vector< token > tokenize ( const std::string & src)
static

◆ transform_nested_functions()

std::optional< file_operations::tmp_file > transform_nested_functions ( const std::string & source_path)

Transforms GCC nested function definitions in a C source file into standard C by lambda-lifting them to file scope.

Captured variables from enclosing scopes become explicit pointer parameters (for direct calls) or file-scope static pointer variables (when the nested function is used as a function pointer).

Returns nullopt if no nested functions are detected (fast no-op). Otherwise returns a tmp_file whose path() contains the transformed source. The caller should pass that path to Clang instead of the original.

◆ transform_one_pass()

std::string transform_one_pass ( const std::string & src)
static

◆ try_parse_func_def()

bool try_parse_func_def ( const std::vector< token > & toks,
size_t idx,
const std::string & enclosing_name,
nested_func & out,
size_t & def_end_tok_idx,
const std::string & src )
static

◆ type_keywords()

const std::set< std::string > & type_keywords ( )
static

◆ usr_stem()

std::string usr_stem ( const std::string & source_path)
static

The source's basename, reduced to characters that read cleanly inside a symbol id.

Two translation units with the same basename collide, exactly as two real file-static functions of the same name in same-named files do.