This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/TM4C1294NCPDT: TI ARM compiler C++ constexpr issue

Part Number: TM4C1294NCPDT

Tool/software: TI C/C++ Compiler

Hello. I am using TI ARM Compiler v18.1.1 LTS which supports c++14 and constexpr to compile the code:



class MyClass { public: constexpr MyClass (const char* str) : mystr() { mystr[0] = 1; } private: char mystr[16]; }; constexpr MyClass A("This is a constant literal");


The compiler throws the error at the last line:

#28 expression must have a constant value test.hpp

There is no problem if i remove the assignment inside the constructor. Also it compiles fine if i make the constructor empty and leave the assignment.

I was testing that code with x86 GCC 5.3.0 and it compiles fine.

  • Hello Igor,

    A constexpr constructor is just like a constexpr function, except that it must initialize the data members in the member-initializer part and those initializations must involve only potential constant expressions, and its body is empty.

    The restriction on the body is quite natural for the kind of types people most often want in ROM.

    Here is an example

    struct complex {

    constexpr complex(double x=0,double y=0) : re(x), im(y) { }
    constexpr double real() { return re; }
    constexpr double imag() { return im; }

    private:

    double re;
    double im;

    };

  • class MyClass {
    public:
        constexpr MyClass (const char* str) : mystr( str ) {};
    //    constexpr mystr()
    //    {
    //        mystr = str;
    //    }
    private:
        const char* mystr;
    };
    MyClass A("This is a constant literal");

  • Hello Tom!

    Thank you for response.

    The C++14 standard actually reduces restrictions for a constexpr constructor's body. https://en.cppreference.com/w/cpp/language/constexpr

    This allows to use the constructor's body.

    The goal of my code in the first post is not to just store the literal string but to process and convert it, then store the result at mystr buffer. This should be done at compile time so i can put MyClass instance to the ROM. I have simplified the code for the sake of showing the compiler error.

    Best regards!

  • Igor,

    this announcement: e2e.ti.com/.../736287
    www.ti.com/.../ARM-CGT-18

    ARM Compiler User Guide 18.9.0.STS
    5.2 Characteristics of ARM C++
    Constant expressions for target-specific types are only partially supported.
  • Tom,
    Thank you for the links! I am not quite able to understand what does the 'target-specific types' mean. Is it non-fundamental types?
  • If they do not exclude the fundametal types from 'the target-specific types' it could be everything.
  • Hi Igor,

    This is in response to the main post regarding source code that results in an error.

    I presume that our compiler is complaining that the implicit use of 'this' in the constructor is causing the problem:

    > armcl a.cpp -pdv
    "a.cpp", line 12: error: expression must have a constant value
      constexpr MyClass A("This is a constant literal");
                          ^
    "a.cpp", line 6: note: attempt to access expired storage
        mystr[0] = 1;

    I have confirmed that both recent versions of gcc and clang compile this code correctly, and we'll be investigating this as a bug. The tracking number for this bug is CODEGEN-5486.

    Until this bug is resolved, you may work around the issue by wrapping the definition of this class with a constexpr function:

    class MyClass {
    public:
    constexpr MyClass (const char* str) :
    mystr() 
    {
      mystr[0] = 1;
    }
    private:
    char mystr[16];
    };
    constexpr MyClass getA()
    { MyClass A("This is a constant literal"); return A; }

    This compiled for me using ARM 18.1.1.LTS.

    As a response to the statement about target-specific types: that term is used to describe types which are implementation-defined. For example, the TI C6000 platform has the x128_t to represent 4 32-bit registers in a 'pair' format. Our ARM implementation does not contain any of these types.