从gcc源码浅谈constexpr

constexpr函数是如何在编译期执行的?constexpr函数局部变量以及循环是如何实现?constexpr if是什么原理?或许你有不少疑惑,但目前关于constexpr编译期的资料还比较少,本文笔者将从 gcc 的源码简单分析一下,以此来抛砖引玉,让更多的人加入到对constexpr的讨论中。

我用的是最新的gcc 11源码,直接翻到gcc/gcc/cp/constexpr.cc,在这个文件里我们可以看到gcc是如何解析constexpr的。

我们先介绍几个重要的数据结构

tree是gcc内部的语法树。

constexpr_call是gcc内部对constexpr函数的包装,它将函数定义、函数参数以及函数结果打包在一起,以便进行编译期求值。可将其和标准库的std::function类比一下,具体结构如下

struct constexpr_call {
   
  /* constexpr函数定义  */
  constexpr_fundef *fundef;
  /* 打包的constexpr函数参数  */
  tree bindings;
  /* 函数调用结果
  	1. NULL表示constexpr函数正在被求值
  	2. error_mark_node表示求值出现错误
  	3. 其他值则表示正确的调用结果 */
  tree result;
  ...
};

constexpr_global_ctx是全局constexpr上下文,每个cxx_eval_outermost_constant_expr(),即最外层的constexpr调用都需要有一个全局constexpr上下文,保存着表达式内部变量到到初始化值的映射,具体结构如下

struct constexpr_global_ctx {
   
  /* 保存常量表达式内部的局部变量或临时变量 */  
  hash_map<tree,tree> values;
  /* 在计算最外层常量表达式时创建的堆 */
  auto_vec<tree, 16> heap_vars;
  /* 待释放的堆数量 */  
  unsigned heap_dealloc_count;
  ...
};

constexpr_ctx是constexpr上下文,具体结构如下

struct constexpr_ctx {
   
  /* 当前的全局constexpr上下文  */
  constexpr_global_ctx *global;
  /* 正在求值的constexpr函数  */
  constexpr_call *call;
  /* 保存当前循环的表达式,如果没有在循环中则为 NULL */  
  vec<tree> *save_exprs;
  /* 当前constexpr对象的构造函数  */
  tree ctor;
  /* 正在构造的constexpr对象.  */
  tree object;
  ...  
};

用于编译期constexpr调用栈的上下文

// 调用栈
static vec
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值