<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Apr 26, 2011, at 8:06 PM, Talin wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">Hi folks - I've decided to try building the Tart compiler using clang, and I've managed to get everything to compile (whew!) but I'm getting a strange runtime error which doesn't occur when I compile my code under gcc.<div>
<br></div><div>Let me explain what the code is doing. As you know, when you have a template that has a static data member, the compiler generates a separate copy of that data member for each instantiation of the template. I often use this feature to generate static data structures from a set of template parameters. In this particular case, I'm using it to construct function signatures for the intrinsic (built-in) functions of my compiler.</div>
<div><br></div><div>The function signature includes an array of parameter definitions, each having a type, a name, and so on. They are defined using a template that looks like this:</div><div><br></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<div><div><font class="Apple-style-span" face="'courier new', monospace">/// -------------------------------------------------------------------</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">/// Template that generates a static formal parameter literal.</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<int type, int index, int paramFlags = 0></font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">class StaticParamDefn {</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">public:</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace"> static ParameterDefn value;</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">};</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div></div><div><div>
<font class="Apple-style-span" face="'courier new', monospace">template<int type, int index, int paramFlags></font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">ParameterDefn StaticParamDefn<type, index, paramFlags>::value(</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace"> NULL,</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace"> ParameterName<index>::value,</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace"> &StaticType<type>::value, paramFlags);</font></div></div></blockquote><div><div><br></div></div><meta http-equiv="content-type" content="text/html; charset=utf-8"><div>
This creates a static instance of the ParameterDefn structure. The <font class="Apple-style-span" face="'courier new', monospace">ParameterName<index>::value</font> expression evaluates to a constant string such as "a0", "a1", "a2" and so on. Similarly the <span class="Apple-style-span" style="font-family: 'courier new', monospace; ">&StaticType<type>::value </span>expression evaluates to a pointer to a type object. The static type objects are defined in a .cpp file, and they look like this:</div>
<div><br></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_Bool>::value = BoolType::instance;</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_Void>::value = VoidType::instance;</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_Char>::value = CharType::instance;</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_SInt8>::value = Int8Type::instance;</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_SInt16>::value = Int16Type::instance;</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_SInt32>::value = Int32Type::instance;</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_SInt64>::value = Int64Type::instance;</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_UInt8>::value = UInt8Type::instance;</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_UInt16>::value = UInt16Type::instance;</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_UInt32>::value = UInt32Type::instance;</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_UInt64>::value = UInt64Type::instance;</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_Float>::value = FloatType::instance;</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_Double>::value = DoubleType::instance;</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace">template<> Type & StaticType<TypeId_UnsizedInt>::value = UnsizedIntType::instance;</font></div></div></blockquote><div>
<br></div><div>This template would normally be invoked like this:</div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; "><br></span></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<div><span class="Apple-style-span" style="font-family: 'courier new', monospace; ">&StaticParamDefn<TypeId_SInt32, 1, ParameterDefn::Variadic>::value,</span></div></blockquote><div><br></div><div>OK, so now let me explain the problem I'm seeing. The ParameterDefn class has an assert(type != NULL) in its constructor, to insure that the type argument is non-NULL. It's this assertion that is failing under clang but not under gcc. I should note that the name parameter is fine, it's only the type parameter that is problematic.</div>
<div><br></div></blockquote><br>I assume that the ParameterDefn constructor is being called as part of the static constructors?</div><div><br><blockquote type="cite"><div>I suspect that the problem is related to the order in which static constructors are being invoked. I'm guessing that the "Type &" variables are actually pointers, and the values are being initialized after the ParameterDefn constructor runs. I had always assumed that the Type & pointers were filled in at compile time, since I never had a problem with this before.</div></blockquote><div><br></div>That's very possible. GCC is more aggressive about optimizing away static constructors than Clang is, and we've seen a few cases where people have depended on GCC's optimizations here to get the right semantics.</div><div><br><blockquote type="cite"><div>My question is - is there any way to make this work under clang?</div></blockquote><div><br></div><div>Well, there's the init_priority attribute. You could try that.</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>- Doug</div><div><br></div></div></body></html>