[cfe-dev] Runtime error with static template members

Douglas Gregor dgregor at apple.com
Fri May 6 07:21:32 PDT 2011


On Apr 26, 2011, at 8:06 PM, Talin wrote:

> 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.
> 
> 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.
> 
> 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:
> 
> /// -------------------------------------------------------------------
> /// Template that generates a static formal parameter literal.
> template<int type, int index, int paramFlags = 0>
> class StaticParamDefn {
> public:
>   static ParameterDefn value;
> };
> 
> template<int type, int index, int paramFlags>
> ParameterDefn StaticParamDefn<type, index, paramFlags>::value(
>   NULL,
>   ParameterName<index>::value,
>   &StaticType<type>::value, paramFlags);
> 
> This creates a static instance of the ParameterDefn structure. The ParameterName<index>::value expression evaluates to a constant string such as "a0", "a1", "a2" and so on. Similarly the &StaticType<type>::value expression evaluates to a pointer to a type object. The static type objects are defined in a .cpp file, and they look like this:
> 
> template<> Type & StaticType<TypeId_Bool>::value = BoolType::instance;
> template<> Type & StaticType<TypeId_Void>::value = VoidType::instance;
> template<> Type & StaticType<TypeId_Char>::value = CharType::instance;
> template<> Type & StaticType<TypeId_SInt8>::value = Int8Type::instance;
> template<> Type & StaticType<TypeId_SInt16>::value = Int16Type::instance;
> template<> Type & StaticType<TypeId_SInt32>::value = Int32Type::instance;
> template<> Type & StaticType<TypeId_SInt64>::value = Int64Type::instance;
> template<> Type & StaticType<TypeId_UInt8>::value = UInt8Type::instance;
> template<> Type & StaticType<TypeId_UInt16>::value = UInt16Type::instance;
> template<> Type & StaticType<TypeId_UInt32>::value = UInt32Type::instance;
> template<> Type & StaticType<TypeId_UInt64>::value = UInt64Type::instance;
> template<> Type & StaticType<TypeId_Float>::value = FloatType::instance;
> template<> Type & StaticType<TypeId_Double>::value = DoubleType::instance;
> template<> Type & StaticType<TypeId_UnsizedInt>::value = UnsizedIntType::instance;
> 
> This template would normally be invoked like this:
> 
> &StaticParamDefn<TypeId_SInt32, 1, ParameterDefn::Variadic>::value,
> 
> 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.
> 

I assume that the ParameterDefn constructor is being called as part of the static constructors?

> 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.

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.

> My question is - is there any way to make this work under clang?

Well, there's the init_priority attribute. You could try that.

	- Doug

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20110506/7082b56c/attachment.html>


More information about the cfe-dev mailing list