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: ARM CGT v5.2.5 Issue with template argument in base class



Tool/software: TI C/C++ Compiler

Hi,

I have an issue with using a template argument in a base class. It looks like the compiler doesn't notice the base class at all. Even my actual code is a bit more complex the following code snippet demonstrates the issue:

template <class T1>
class Foo
{
    public:
        T1  p1;
        virtual void dump() {
            printf("%08X: %i\n", this, p1);
        }
};

template <class T1, class T2>
class Bar : public Foo<T1>
{
    public:
        T2  p2;
        virtual void dump() {
            printf("%08X: %i, %i\n", this, p1, p2); // error #20: identifier "p1" is undefined
        }
};

void test()
{
        Bar<int, int> bar;
        bar.p1 = 1; // ok !!!
        bar.p2 = 2;
        bar.dump();
}

Accessing a base class member in the implementation of the derived class throws compiler error #20 (identifier undefined). Doing the same from outside the class seems to work.

The same code works fine with MS VC.

I am using DM814x, SYS/BIOS v6.35.06.56, XDCTools v3.25.06.96 and ARM CGT v5.2.5. (I quickly tried to update to ARM CGT 18.1.2, it seems to have the same issue, despite some other problems in the libcxx include files ...)

Any idea?

Thanks, Lars

  • Lars Beikirch said:
    Accessing a base class member in the implementation of the derived class throws compiler error #20 (identifier undefined).

    I get a similar error when I use a recent version of GNU g++.  So I am confident the TI compiler is correct.  I'm sure you want more explanation.  I am getting some help on that.

    Thanks and regards,

    -George

  • A template is parsed twice: Once when it is first seen, and another when it is instantiated. In the first pass, T1 and T2 are unknown placeholder types, and in the second, they are known to be types <int,int>.

    In the code you've posted, Foo<T1> is a dependent base class of Bar, which means that its contribution to Bar can't be determined until the second time Bar is parsed, when T1 and T2 are known. When dealing with a dependent base class, the default name lookup does not work, because consider what happens when the following specialization of Foo is added:

    template <>
    class Foo<int>
    {
        public:
            virtual void dump() {
                printf("%08X:\n", this);
            }
    };

    Now, the code may or may not be ill-formed depending on the type of 'T1'. Since the language can't determine this when parsing the template with T1 and T2 unknown, it must defer the check until later, when it knows for sure. Additionally, it must be conservative and assume that since no global 'p1' is available, that it is a reference to an undefined variable.

    How do we fix this? We can defer the name lookup later by linking the reference to 'p1' to a dependent entity. Since Bar is dependent due to the inheritance of a dependent base class, we can reference p1 through the 'this' pointer. The following code compiles.

    #include <stdio.h>
    
    template <class T1>
    class Foo
    {
        public:
            int  p1;
            virtual void dump() {
                printf("%08X: %i\n", this, p1);
            }
    };
    
    template <class T1, class T2>
    class Bar : public Foo<T1>
    {
        public:
            T2  p2;
            virtual void dump() {
                printf("%08X: %i, %i\n", this, this->p1, p2); // Reference a dependent member variable through the dependent 'this' pointer
            }
    };
    
    void test()
    {
            Bar<int, int> bar;
            bar.p1 = 1; // ok !!!
            bar.p2 = 2;
            bar.dump();
    }

  • Hi James,

    thanks a lot for the detailed explanation and for your suggestion to fix my problem. It works fine now. :)

    BR, Lars