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.

[参考译文] 编译器/C6000-CGT:CGT 8.3.x 中的枚举

Guru**** 2535150 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/881731/compiler-c6000-cgt-enumerations-in-cgt-8-3-x

器件型号:C6000-CGT

工具/软件:TI C/C++编译器

您好!

我们正在测试新的编译器版本8.3.4并验证(也使用 CGT 8.3.6)、在某些特定情况下存在编译失败、而 CGT7未出现这种情况。 我要附加示例代码(使用命令来生成)以重现问题:


typedef 枚举
{
A = 1、
B、
C
}X;

无符号 Fun (X param)
{
const unsigned int y[]={param};

返回 y[0];
}

int main()
{
无符号 i = 0;

i =趣味(c);

if (i>0)
{
;
}
}

e2e.ti.com/.../enum_5F00_issue_5F00_for_5F00_TI.zip

编译器错误:

"./main.cpp"、第10行:错误#2721-D:从"X"到"unsigned int"的无效缩窄转换
在编译"./main.cpp"时检测到1错误。

>>编译失败

使用 wandbox 的在线编译器进行了更深入的调查、以获得参考结果(GCC/Clang 均已选中)。 初始参考代码:

#include 
#include 


typedef 枚举
{
A = 1、
B、
C
}X;

void Fun (X param)
{
const unsigned int y[]={param};

std:::cout <<"value of y="<< y[0]<< std:endl;
}

int main ()
{
const unsigned int x[]={a、b、c};

娱乐(c);

std:::cout <<"值:"<< x[0]<<"、"<< sizeof (a)<<"、"<< sizeof (X)<< std:endl;
}

带输出:

y=3的值
值:1、4、4
0

我们在 CGT 中观察到的错误是由 C++11引入的-为阵列初始化缩小转换范围意味着程序格式不正确(在此处查找"缩小转换范围"短语: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf)。 要触发此错误、 可稍微更改代码:

#include 
#include 


typedef 枚举
{
A = 1、
b = UINT_MAX、
C
}X;

void Fun (X param)
{
const unsigned int y[]={param};

std:::cout <<"value of y="<< y[0]<< std:endl;
}

int main ()
{
const unsigned int x[]={a、b、c};//使用 b = 2、不使用 b = UINT_MAX

tFun (c);//导致错误。

std:::cout <<"值:"<< x[0]<<"、"<< sizeof (a)<<"、"<< sizeof (X)<< std:endl;
}

检测到错误:

PROG.cc:在函数"void Fun (X)"中: 
prog.cc:14:32:错误:将"param"的转换从"long unsigned int"缩窄到"unsigned int"[-Wthing] 
  14 |    const unsigned int y[]={param}; 
     |                               ^~~~~μ A 
prog.cc:在函数'int main()'中: 
prog.cc:21:39:错误:将'c'的转换从'long unsigned int'缩窄到'unsigned int'[-Wthing] 
  21 |    const unsigned int x[]={a、b、c}; //使用 b = 2、不使用 b = UINT_MAX 
     |                                      ^μ A 
1 

要有完善的计划、应修改:

#include 
#include 


typedef 枚举
{
A = 1、
b = UINT_MAX、
C
}X;

void Fun (X param)
{
const unsigned long int y[]={param};

std:::cout <<"value of y="<< y[0]<< std:endl;
}

int main ()
{
const unsigned int x[]={A};

娱乐(c);

std:::cout <<"值:"<< x[0]<<"、"<< sizeof (a)<<"、"<< sizeof (X)<< std:endl;
}

具有以下输出:
y=4294967296的值 
值:1、8、8 
0 
值得注意的是、当警告不被识别为错误时、第一个错误显示为警告。 不过、该示例显示了在 C++ 11中如何检测转换是否变窄。
 
返回 CGT 的示例代码、使用在线编译器轻松编译... 当函数的参数为 枚举类型(将枚举值直接分配给数组不会触发问题)时、CGT8似乎限制性太强。 当第10行中的数组类型更改为 int 类型时、它会起作用。 如果最后一个枚举值是 int (2147483647)的最大值、则仍然不起作用、但当它等于2147483648 (范围对于无符号 int 有效)时、问题消失。 我们知道、在规范中、int 类型用于枚举表示、但看起来编译器错误地识别了从 int 到 unsigned 的转换范围(尽管事实上、对于此特定的枚举精度不会丢失)、并以非标准方式运行。
 
我们发现、已经存在一个有关向 TI 报告的枚举的问题(CodeGen-3740)、而且这里描述的问题可能具有相同的根本原因。
 
 
此致、
ZD

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [报价用户="user6284149"]关于向 TI 报告的枚举,已经存在一个问题(CodeGen-3740)[/报价]

    我同意问题是类似的。  但我不确定这是同一个问题。  因此、我提交了问题 EXT_EP-9680、以调查您的具体情况。  欢迎您通过我签名中的以下链接进行跟踪。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢你。 对于我们来说、将此更正 (以及其他报告的问题)与 RSA 内在函数(我假设您知道我要向哪个请求重新发送)一起进行非常重要、因此所有重要的修复都可以包含在一个编译器的版本中。

    最好的再加勒

    ZD

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这里有很多事情要做、所以请多多包涵。

    首先、我要说的是、诊断不是一个错误;实际上、正如 C++ 11中所描述的那样、存在一个"正在缩小转换范围"。 我将解释出现诊断的原因以及如何调整代码以解决该问题。

    给定您的枚举:

    typedef enum { a = 1, b, c } X;

    与在 C 语言中不同、X 类型是枚举类型、而不是整数类型。 这是混合类型表达式中一种微妙但至关重要的差异。 确实、"内幕揭秘"、编译器必须为 C 和 C++中的枚举类型选择一个基础整数类型、对类型"X"的值和变量的处理方式与 C++中的整数类型略有不同。

    枚举常量(a、b、c)范围为[1、3]。 出于我不会在该线程中深入探讨的原因、编译器选择"signed int"类型作为基础类型。 由于此类型是有符号的、因此可以为类型 X 的变量分配负值。不允许编译器假设类型 X 的变量只能具有值 a、b 或 c 中的一个

    现在您有了以下行:

    const unsigned int y[] = { param };

    此处"param"为 X 类型。请记住、X 可能具有负值、而"unsigned int"不能表示负值。 在 C++11 (dcl.init.list)中、"缩小转换范围"(部分)定义为:"隐式转换[.] 从整数类型或非范围枚举类型到不能表示原始类型的所有值的整数类型、除非源是常量表达式[...]" 显然、这是从"X"(有符号)转换为"unsigned int"、因此这是一个变窄。 请注意、另一方向的转换也将缩小;"signed int"不能代表"unsigned int"的所有值。 正如您发现的、C++11标准指出、具有"缩小转换"的列表初始化程序"格式不正确"。

    您可以通过更改以下行来消除诊断:

    const unsigned int y[] = { param };

    为此:

    const X y[] = { param };

    这可以避免转换、从而避免诊断。

    或者、您可以通过对枚举使用固定类型(A C++11功能)来消除诊断:

    typedef enum : unsigned int { a = 1, b, c } X;

    现在、您为什么没有收到 GCC 的此警告?

    由于我不会在该线程中使用的原因、GCC 为基础类型选择了"unsigned int"类型、而 TI 编译器选择了"signed int"类型。 因此、对于 GCC、在从"X"到"unsigned int"的隐式转换中、目标能够表示"X"的所有值、因此它不是一个狭窄的转换、因此您不会得到诊断。

    当您设置"b = UINT_MAX"时、会强制"c"为"UINT_MAX+1"、这超过了"unsigned int"的大小、这会导致基础类型具有下一个更高的大小、"unsigned long"、对于您正在使用的 GCC、它是64位类型。 现在、由于并非所有"X"值都可以表示为"无符号整型"(例如"c")、因此转换将会变窄、因此列表初始化中的诊断也会变小。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    这一回答非常详细、并且澄清了所有问题。 我在这里检查以确保(未范围的枚举、第1点):

    https://en.cppreference.com/w/cpp/language/enum

    直接在 C++11标准文档(第7.2章、第7点)中、例如此处:

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf

    它是由实现定义的、枚举的表示方式、因此 CGT 和 GCC 都可以自行选择枚举。 这不是错误。 而 C++11具有"固定底纹类型的枚举"功能、您建议使用该解决方案来解决项目中的差异。 在这方面没有其他需要讨论的问题。 感谢您的支持。

    此致、

    ZD