简体   繁体   English

clang中的constexpr错误但不是gcc中的错误?

[英]constexpr bug in clang but not in gcc?

Let's take this simple example: 我们来看一个这个简单的例子:

#include <iostream>

namespace foo {
    constexpr int main(int argc, char* argv[]) {
      // code
    }
}

int main(int argc, char* argv[])
{
    return foo::main(argc, argv);
}

Depend on what code is, clang will complain or no. 取决于代码是什么,clang会抱怨或不抱怨。 If code is: 如果代码是:

cout << "Hello!";
return 0;

clang complains: clang抱怨:

error: constexpr function never produces a constant expression [-Winvalid-constexpr] 错误:constexpr函数永远不会产生常量表达式[-Winvalid-constexpr]

 constexpr int main(int argc, char* argv[]) { 

note: non-constexpr function 'operator<< >' cannot be used in a constant expression 注意:非constexpr函数'operator <<>'不能用于常量表达式

  std::cout << "Hello!"; 

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:530:5: note: declared here /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:530:5:注意:在这里声明

 operator<<(basic_ostream<char, _Traits>& __out, const char* __s) 

Fair enough, constexpr functions can't contain any cout statements, as we know. 很公平,constexpr函数不能包含任何cout语句,我们知道。 But what happens if we do this? 但是如果我们这样做会发生什么?

  for (int i = 0; i < argc; i++)
    std::cout << argv[i];

clang allows it! clang允许它! OK, but this can't possibly be a constexpr function even though it is marked constexpr, let's try to use it in constexpr context. 好吧,但这不可能是一个constexpr函数,即使它被标记为constexpr,让我们尝试在constexpr上下文中使用它。

int arr[foo::main(argc, argv)];

It works! 有用! So it must be clang bug? 那一定是cla​​ng bug? Reason I say clang because gcc complains: 我之所以说clang是因为gcc抱怨:

error: body of constexpr function 'constexpr int foo::main(int, char**)' not a return-statement 错误:constexpr函数的主体'constexpr int foo :: main(int,char **)'不是return语句

So my conclusion is clang is wrong and gcc is right. 所以我的结论是铿锵有误,而gcc是对的。

Clang is correct here. Clang在这里是正确的。

First example 第一个例子

Here, the code is: 这里的代码是:

constexpr int foo::main(int argc, char* argv[]) {
  std::cout << argv[i];
  return 0;
}

In C++11 , this code is ill-formed, because the body contains an expression-statement , which is not permitted in a constexpr function definition. 在C ++ 11中 ,此代码格式错误,因为正文包含一个表达式语句 ,这在constexpr函数定义中是不允许的。

In C++1y , this code is ill-formed with no diagnostic required, because a call to foo::main can never produce a constant expression (because it always calls operator<<(std::ostream&, const char*) , which is not constexpr ). 在C ++ 1y中 ,此代码格式错误 ,无需诊断,因为对foo::main的调用永远不会产生常量表达式(因为它总是调用operator<<(std::ostream&, const char*) ,这不是constexpr )。

Second example 第二个例子

In this case, the code is: 在这种情况下,代码是:

constexpr int foo::main(int argc, char* argv[]) {
  for (int i = 0; i < argc; i++)
    std::cout << argv[i];
  return 0;
}

In C++11 , this code is ill-formed, because it contains a for -statement. 在C ++ 11中 ,此代码格式不正确,因为它包含for statement。

In C++1y , this code is valid. 在C ++ 1y中 ,此代码有效。 In particular, foo::main(0, 0) is a constant expression (with value 0 ). 特别是, foo::main(0, 0)是一个常量表达式(值为0 )。 Since foo::main is usable in a constant expression, Clang is not permitted to reject it, and does not do so. 由于foo::main可用于常量表达式,因此不允许Clang拒绝它,也不允许拒绝它。

Third example 第三个例子

int arr[foo::main(argc, argv)];

The array bound here is not a constant expression (because it reads argc and argv , which are not constant). 这里绑定的数组不是常量表达式(因为它读取argcargv ,它们不是常量)。 However, Clang supports variable-length arrays as an extension by default. 但是,Clang默认支持可变长度数组作为扩展。 You can specify -pedantic-errors to put clang into strictly-conforming mode, and in that mode it will reject this code. 您可以指定-pedantic-errors将clang置于严格一致的模式,并且在该模式下它将拒绝此代码。

GCC's diagnostic: 海湾合作委员会的诊断:

error: body of constexpr function 'constexpr int foo::main(int, char**)' not a return-statement 错误:constexpr函数的主体'constexpr int foo :: main(int,char **)'不是return语句

is incorrect in both C++11 and C++1y. 在C ++ 11和C ++ 1y中都是不正确的。 In C++11, it's incorrect because the rule is more subtle (the body of a constexpr function can contain typedef s and a few other constructs, not just return -statements). 在C ++ 11中,它是不正确的,因为规则更加微妙( constexpr函数的主体可以包含typedef和一些其他结构,而不仅仅是return -statements)。 In C++1y, the rule no longer exists at all. 在C ++ 1y中,规则根本不存在。

You compile your code in C++1y mode which contains wording to relax constexpr restrictions including all looping statements. 您可以在C ++ 1y模式下编译代码,其中包含用于放宽constexpr限制(包括所有循环语句)的措辞。

Have a look at N3652 which introduced these changes. 看看介绍这些变化的N3652

So gcc 4.8.1 does not implement relaxed constexpr restraints, but clang 3.5 does. 所以gcc 4.8.1没有实现轻松的constexpr限制,但是clang 3.5确实如此。 My mistake was that clang and gcc both have variable length array extensions. 我的错误是clang和gcc都有可变长度的数组扩展。 if I had used std::array instead, both compilers would reject the code. 如果我使用了std :: array,两个编译器都会拒绝代码。 What I still don't understand is if clang allows relaxed constexpr, then why is it not a constexpr? 我仍然不明白的是,如果clang允许放松constexpr,那么为什么它不是constexpr?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM