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/TMS320C6747: Unable to compile template code

Part Number: TMS320C6747
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI C/C++ Compiler

I believe there is an error in the compiler as it appears to be incorrectly attempting to compile a non-array version of a template when it should have compiled the array version.

The following code is generating this error:  

subdir_rules.mk:23: recipe for target 'main.obj' failed
"../main.cpp", line 159: error #138: expression must be a modifiable lvalue

Here is the code:

/*
* ======== main.c ========
*/

#include <xdc/std.h>

#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>

#include <ti/sysbios/BIOS.h>

#include <ti/sysbios/knl/Task.h>


#include <typeinfo>


/*
* ======== taskFxn ========
*/
Void taskFxn(UArg a0, UArg a1)
{
System_printf("enter taskFxn()\n");

Task_sleep(10);

System_printf("exit taskFxn()\n");
}

typedef unsigned int uint32;
typedef unsigned short uint16;

namespace Internal
{
class Eraser
{
public:
template <typename T>
Eraser(const T& t)
: mpData(new Impl<T>(t))
{
}

template <typename T, std::size_t I>
Eraser(const T (&t)[I])
: mpData(new ArrayImpl<T>(t, I))
{
}

~Eraser()
{
delete mpData;
}

void* GetData()
{
return mpData->GetData();
}

private:

struct Interface
{
virtual ~Interface()
{
}
virtual void* GetData() = 0;
};

template <typename T>
class Impl : public Interface
{
public:
Impl(const T& t)
: mpData(new T(t))
{
}
virtual ~Impl()
{
delete mpData;
}

virtual void* GetData()
{
return mpData;
}

private:
T* mpData;
};

template <typename T>
class ArrayImpl : public Interface
{
public:
ArrayImpl(const T* t, std::size_t count)
: mpData(new T[count])
{
for(std::size_t i = 0; i < count; ++i)
{
mpData[i] = t[i];
}
}
virtual ~ArrayImpl()
{
delete[] mpData;
}

virtual void* GetData()
{
return mpData;
}

private:
T* mpData;
};

mutable Interface* mpData;
};
}


class ElementInfo
{
public:
ElementInfo()
: mpDataType(0)
, mpData(0)
{
}

const std::type_info& GetDataType()
{
return *mpDataType;
}

Internal::Eraser* GetData()
{
return mpData;
}

private:
const std::type_info* mpDataType;
Internal::Eraser* mpData;
};

int mCurrentSize = 10;
ElementInfo* mpElements;

// Set, template non-array version
template <typename T>
void Set(uint32 dataId, const T& data)
{
if (dataId < mCurrentSize)
{
// In CCS, This line results in error: "../main.cpp", line 165: error #138: expression must be a modifiable lvalue
*reinterpret_cast<T*>(mpElements[dataId].GetData()->GetData()) = data;
}
}

// Set, template array version.
template <typename T, std::size_t I>
void Set(uint32 dataId, const T(&data)[I])
{
if (dataId < mCurrentSize)
{
for (uint32 i = 0; i < I; ++i)
{
reinterpret_cast<T*>(mpElements[dataId].GetData()->GetData())[i] = data[i];
}
}
}

Void RunTestCode()
{
int maxNumberOfElements = mCurrentSize;
mpElements = new ElementInfo[maxNumberOfElements];

uint32 dataId0 = 1;

uint16 dataValue = 100;
Set(dataId0, dataValue);

const uint32 arraySize = 3;
//const uint16 dataArray[arraySize] = { 0, 0, 0 }; // Using this line instead of the next line fixes a problem in the compiler.
uint16 dataArray[arraySize] = { 0, 0, 0 };

// Retrieving the first element using the wrong data type should fail.
Set(dataId0, dataArray);
}

/*
* ======== main ========
*/
Int main()
{
RunTestCode();

/*
Task_Handle task;
Error_Block eb;

System_printf("enter main()\n");

Error_init(&eb);
task = Task_create(taskFxn, NULL, &eb);
if (task == NULL) {
System_printf("Task_create() failed!\n");
BIOS_exit(0);
}
*/

//BIOS_start(); /* does not return */
return(0);
}

  • What compiler options are you using? What version of the compiler are you using (it is not the same as the CCS version)
  • Should be the latest. I downloaded the lastest CCS 7.2 two days ago. Here is more of the compile output:

    **** Build of configuration Debug for project TemplateTest2 ****

    "C:\\ti\\ccs720\\ccsv7\\utils\\bin\\gmake" -k -j 12 all -O
    making ../src/sysbios.ae674 ...
    gmake[1]: Nothing to be done for 'all'.
    'Building file: ../main.cpp'
    'Invoking: C6000 Compiler'
    "C:/ti/ccs720/ccsv7/tools/compiler/c6000_7.4.22/bin/cl6x" -mv6740 --abi=eabi -g --include_path="C:/Bently/CCS_7_2_Workspace/TemplateTest2" --include_path="C:/ti/ccs720/ccsv7/tools/compiler/c6000_7.4.22/include" --define=c6748 --diag_wrap=off --diag_warning=225 --display_error_number --preproc_with_compile --preproc_dependency="main.d" --cmd_file="configPkg/compiler.opt" "../main.cpp"
  • It does appear to be a bug, but it looks like the bug has been fixed in the C6000 8.x compiler versions. I'm going to need to refer this one to an expert on the topic.
  • The C++ parser was upgraded between 7.4.x and 8.x, and as noted, the 8.x compiler now handles the code the way you expect. If you can upgrade to 8.x, please consider doing so. If not, you'll need to use the workaround you show above. I've submitted CODEGEN-3568 for further analysis. However, this bug will not have high priority, as it seems to already be fixed in 8.x. If this does end up being a bug, and the fix is extensive, there is a possibility it won't be fixed for 7.4.x at all. I'm sorry I don't have a more definitive disposition for this bug.