是gcc认为内置的非常量表达式函数是常量表达式 [英] Is gcc considering builtins of non-constant expression functions to be constant expressions

查看:261
本文介绍了是gcc认为内置的非常量表达式函数是常量表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请参阅更新以了解问题的更好示例。 此问题为什么我可以在constexpr函数中调用非constexpr函数?提供了下面的代码



  #include< stdio.h> 

constexpr int f()
{
return printf(a side effect!\\\
);
}

int main()
{
char a [f()];
printf(%zd \\\
,sizeof a);
}

我回答的是错误的 gcc 4.8.2 允许它(



但是,如果我们使用 -fno-builtin flag gcc 产生错误( 看到它现场 ):

 错误:调用非constexpr函数'int printf char *,...)'
return printf(a side effect!\\\
);
^

所以它似乎 gcc 正在考虑其内置版本的 printf 是一个常量表达式。 gcc 这里的文件内建< a>但不记录这种情况,其中非constexpr函数的内置函数可以被认为是一个常量表达式。



如果确实是这样:




  • 编译器是否允许这样做?

  • 如果允许, .org / jtc1 / sc22 / wg21 / docs / papers / 2012 / n3485.pdfrel =nofollow> C ++草稿标准 1.4 < em>段 段落表示 b >

    符合的实现可能有扩展(包括附加的库函数),只要它们不改变任何格式良好的程序的行为。 需要使用实施方案来诊断使用根据本国际标准格式不正确的扩展程序的程序。


    更新



    由于Casey指出,原始问题中有一些事情使它成为一个糟糕的例子。一个简单的示例是使用 std :: pow ,这不是一个constexpr函数:

      #include< cmath> 
    #include< cstdio>

    constexpr double f()
    {
    return std :: pow(2.0,2.0);
    }

    int main()
    {
    constexpr double x = f();

    printf(%f \\\
    ,x);
    }

    编译和构建没有警告或错误( 查看实时 ),但添加 -fno-builtin 使其产生错误( 查看实时 )。注意:为什么数学函数在C ++ 11中不是constexpr

     错误:调用非constexpr函数'double pow(double,double)'
    return std :: pow(2.0,2.0);
    ^


    解决方案

    c> gcc 正在考虑一些内置函数作为 constexpr ,即使标准没有明确标记为这样。我们可以在 gcc 错误报告 cmath https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 =nofollow> [C ++ 0x] sinh vs asinh vs constexpr 说:


    LWG 2013似乎允许GCC将这些函数作为constexpr来处理。
    所以,固定为4.7


    这指的是 LWG问题2013 ,其原始提议的解决方案是在 17.6.5.6 [constexpr.functions] 约束,实现可以声明任何函数为
    constexpr [...]


    但是在C ++ 11之后,解析被反转,最终解析结果为:


    [...]实现不应声明任何标准库函数
    signature作为constexpr,除非明确
    需要。 ]


    因此,这是目前的(在C ++ 14 明确不符合的扩展,并且据我所知,这是不符合C ++ 11,因为它改变了可观察的行为,因此不会被允许



    Jonathan Wakely指出了一个 libstdc ++ 邮件列表讨论: PR libstdc ++ / 49813 revisited:constexpr on functions(and builtins)


    我相信我们应该重新打开错误根据LWG 2013的实际分辨率
    (添加constexpr是禁止的)。



    FE不应该将内置作为constexpr严格遵守
    模式。



    我们应该从< cmath>完全删除_GLIBCXX_CONSTEXPR,或者
    使用__STRICT_ANSI __条件。


    < blockquote>

    Please see the update for a better sample of the problem. The original code has a mix of issues which muddies the picture:

    This question Why can I call a non-constexpr function inside a constexpr function? presented the following code

    #include <stdio.h>
    
    constexpr int f()
    {
        return printf("a side effect!\n");
    }
    
    int main()
    {
        char a[f()];
        printf("%zd\n", sizeof a);
    }
    

    Which as I answer is ill-formed but gcc 4.8.2 allows it (see it live).

    But, if we use the -fno-builtin flag gcc generates an error (see it live):

    error: call to non-constexpr function 'int printf(const char*, ...)'
         return printf("a side effect!\n");
                                         ^
    

    so it seems that gcc is considering its builtin version of printf to be a constant expression. gcc documents builtins here but does not document this case where a builtin of a non-constexpr function can be considered a constant expression.

    If this is indeed the case:

    • Is a compiler allowed to to do this?
    • If they are allowed, don't they have to document it to be conformant?
    • Can this be considered an extension, if so, it seems like this would require a warning as the C++ draft standard section 1.4 Implementation compliance paragraph 8 says (emphasis mine):

    A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program. Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.

    Update

    As Casey points out there are a few things going on in the original problem that makes it a poor example. A simple example would be using std::pow which is not a constexpr function:

    #include <cmath>
    #include <cstdio>
    
    constexpr double f()
    {
        return std::pow( 2.0, 2.0 ) ;
    }
    
    int main()
    {
        constexpr double x = f() ;
    
        printf( "%f\n", x ) ;
    }
    

    Compiles and builds with no warnings or error (see it live) but adding -fno-builtin makes it generates an error (see it live). Note: why math functions are not constexpr in C++11:

    error: call to non-constexpr function 'double pow(double, double)'
         return std::pow( 2.0, 2.0 ) ;
                                   ^
    

    解决方案

    Yes, gcc is considering some builtin functions as constexpr even if the standard does not explicitly mark them as such. We can find the discussion that pertains specifically to the math function found in cmath in the gcc bug report [C++0x] sinh vs asinh vs constexpr which says:

    LWG 2013 does seem to allow GCC to treat these functions as constexpr. So, fixed for 4.7

    which is referring to LWG issue 2013 whose original proposed resolution was to add the following to section 17.6.5.6 [constexpr.functions] (emphasis mine going forward):

    [...]Additionally, an implementation may declare any function to be constexpr if that function's definition satisfies the necessary constraints[...]

    but after C++11 the resolution was reversed and the final resolution ended up as:

    [...]An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required.[..]

    So this is currently(in C++14) a explicitly non-conforming extension and as far as I can tell this was non-conforming in C++11 since it alters observable behavior and therefore would not be allowed via the as-if rule.

    Jonathan Wakely points out a libstdc++ mailing list discussion: PR libstdc++/49813 revisited: constexpr on functions (and builtins) where reopening the bug report mentioned above was discussed due to the issues laid out above:

    I believe we should re-open the bug in light of the actual resolution of LWG 2013 (adding constexpr is forbidden).

    The FE should not treat builtins as constexpr in strict-conformance mode.

    We should either remove _GLIBCXX_CONSTEXPR from <cmath> entirely or make it conditional on __STRICT_ANSI__.

    这篇关于是gcc认为内置的非常量表达式函数是常量表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆