<div class="gmail_quote">On Fri, May 18, 2012 at 9:12 AM, Andy Gibbs <span dir="ltr"><<a href="mailto:andyg1001@hotmail.co.uk" target="_blank">andyg1001@hotmail.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

I'd like to learn a little about how clang works on the inside, and would<br>
like to have a go at implementing a new "builtin" function which forces an<br>
expression to be folded to a constant.</blockquote><div><br></div><div>OK. The first thing you need to be aware of is that 'folded to a constant' is not the same as 'evaluated as a constant expression'. The former case just means "take an expression, and use any tricks we know to reduce it to a compile-time constant". The latter means following the relevant language standards, which is a nebulous affair:</div>

<div><br></div><div>* In C{89,99,11}, precise rules are given for "integer constant expressions" (ICEs, which are required in various contexts), as well as for "constant expressions in initializers". However, implementations are allowed to accept other (non-standard) forms of constant expression in initializers, and we do not have an implementation of the standard rules: instead, Expr::isConstantInitializer checks whether an expression is something we can emit as a constant (this is a superset of the set of expressions we can fold to a constant), and we use that to check whether an expression is a constant expression for the purpose of initialization. Expr::isIntegerConstantExpr checks whether an expression is an integer constant expression, following the language standard.</div>

<div><br></div><div>* The situation in C++98 is similar to C, except that "integer constant expression" is renamed to "integral constant expression", and implementations are not allowed to extend what "constant expression" means. However, they are allowed to use constant initialization for dynamic initializers which they are able to evaluate, which has the same consequences.</div>

<div><br></div><div>* The situation in C++11 is completely different. The term "constant expression" is defined to cover a much broader set of cases there (which can be checked by Expr::isCXX11ConstantExpr). Implementations are still permitted to convert dynamic initialization to constant initialization if they can fold an expression.</div>

<div><br></div><div>Additionally, the set of things we can fold is slightly different in the different languages. Anyway, the point is, outside of C++11, we don't really have an implemented, checkable notion of 'constant expression' other than 'integer constant expression'.</div>

<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The idea would be that it would<br>
either compile-time-evaluate the expression or halt compilation with an<br>
error.  I believe there isn't anything currently that does this for<br>
arbitrary types, only integers.<br></blockquote><div><br></div><div>For what it's worth, if you want something which folds expressions, I think you can already build that (horrifically):</div><div><br></div><div>// Outside C++11, where everything we can fold has a '!'</div>
<div>struct assert_foldable_t { int arr[1]; };</div><div><div>#define fold(expr) (__builtin_constant_p(1) ? (expr) : (expr))</div><div>#define ignore(expr) ((int)!(expr))</div><div>#define assert_foldable(expr) ((void)(struct assert_foldable_t){.arr[ignore(fold(expr))] = 1})</div>
<div>#define builtin_fold(expr) (assert_foldable(expr), fold(expr))</div></div><div><br></div><div>// In C++11, same as above, except:</div><div>template<typename T> constexpr int ignore(T&&) { return 0; }</div>
<div><div><br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
What I envisage is something like...<br>
<br>
   auto x = __builtin_fold(<expression>)<br>
<br>
which returns a constant value of appropriate type for the expression.<br>
<br>
I'd envisage it as a replacement for an already-possible two-step approach<br>
as follows:<br>
<br>
struct __fold_impl_1<br>
    {<br>
    static constexpr auto value = <expression>;<br>
    };<br>
<br>
...<br>
auto x = __fold_impl_1::value;<br></blockquote><div><br></div><div>As noted above, this evaluates the expression as a constant expression, which isn't the same as folding it.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

The obvious down-side of the two-step approach is requiring a special macro<br>
for generating __fold_impl_xxx for each folded expression, plus the<br>
inconvenience and possible scope problems of having to use such a macro!<br></blockquote><div><br></div><div>If you just wanted C++11 constant expression semantics, you could use something like this:</div><div><br></div>
<div><div>#define builtin_fold(expr) \</div><div>  ([]{ \</div><div>    struct S { \</div><div>      constexpr decltype(expr) get() const { \</div><div>        return (expr); \</div><div>      } \</div><div>    } s; \</div>
<div>    constexpr auto val = s.get(); (void)val; \</div><div>    return s; \</div><div>  }().get())</div></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

I'd also like it to work in non-C++11 code.<br></blockquote><div><br></div><div>Then you will need to either fold rather than evaluate as a constant expression, or implement the full constant expression rules for non-C++11 languages (which would be a great thing to have -- see <a href="http://llvm.org/PR4402">llvm.org/PR4402</a>).</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I could imagine that it should be very possible to get clang to generate<br>
such a struct on-the-fly which avoided the scope problems and substitute the<br>
expression for a reference to the value.<br>
<br>
The questions I have are:<br>
<br>
 - how does one go about getting clang to build such substitutiary code in<br>
this way?<br></blockquote><div><br></div><div>This is the wrong approach :)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 - is this the best approach, or is there a better/simpler way?</blockquote><div><br></div><div>If you want to add a new builtin for this, you should search through the codebase to find the places where builtins are currently handled, and add the relevant support for your builtin there. In particular, you will need to add a new builtin to include/clang/Basic/Builtins.def, add some code to Sema to check that the argument can be folded, and add some code to AST/ExprConstant.cpp to fold the argument. You shouldn't need to change CodeGen, since ExprConstant should be able to fold all occurrences of this builtin.</div>
<div><br></div><div>However, I think a better feature (and one which I would definitely support pushing into trunk clang) would be an attribute which can be applied to declarations (maybe [[clang::const_init]]), which requires the declaration to be initialized by a constant expression. This isn't equivalent to any kind of __builtin_fold, since it would work in cases where there is no expression to wrap in __builtin_fold (such as "T x(1, 2, 3);" or "T x = { 1, 2, 3 };"), and would allow constant initialization to be required for objects with constexpr constructors but non-trivial destructors.</div>
<div><br></div><div>-- Richard</div></div>