GCC和clang中奇怪的构造和析构函数语法(void *返回类型)

时间:2018-11-04 08:39:31

标签: c++ g++ clang clang++

在编写一些C ++代码(使用clang,x86_64 linux编译)时,我不小心编写了以下结构:

With Worksheets(Choose(Arg1, Sheet1.Name, Sheet2.Name)) ' reference Sheet1 if Arg1=1 and Sheet2 if Arg1=2 
    With .Range("C2", .Cells(.Rows.Count, "C").End(xlUp)).Find(what:=chart_label(Arg2), LookIn:=xlValues, lookat:=xlWhole) ' search reference referenced sheet x-values range for current x-value
        score = .Offset(, 2).Value ' assign 'score' the value of found cell offset two columns to the right
        desc = .Offset(, -1).Value ' assign 'desc' the value of found cell offset one column to the left
    End With
End With

即构造函数名称前带有星号(*)。

再尝试一点,我注意到您可以在前面加上任意数量的*;它也适用于析构函数,即

class Class {
    *Class() {}
};

Clang编译时没有任何错误或警告。

GCC发出警告

  

控制到达非无效函数的结尾

这使我相信我实际上是在声明一个返回类型为class Class { ********Class() {} ********~Class() {} }; (或void*)的构造函数/析构函数。并用值编写任何类型的return语句都会产生错误(如预期):

void********

有趣的是,生成的LLVM IR位码正确包含一个void函数:

return nullptr;
return {};
...

搜索与此有关的任何信息都没有得到任何结果。所以我的问题是:这个标准符合C ++还是GCC和Clang的编译器前端中的错误?或者也许是一些兼容性功能?如果正确的话,用例是什么。

1 个答案:

答案 0 :(得分:2)

它看起来像个错误。因为它不符合标准。声明或定义构造函数的标准方法在[class.ctor]/1中:

  

构造函数没有名称。在构造函数的声明中,   声明符是形式的函数声明符

ptr-declarator ( parameter-declaration-clause ) noexcept-specifieropt attribute-specifier-seqopt
     

其中ptr声明符仅由一个id表达式组成,   可选的attribute-specifier-seq和可选的环境   括号,并且id表达式具有以下形式之一:

     
      
  • 在属于类的成员规范但不是朋友声明的成员声明中,id-expression为   立即封闭类的注入类名称;
  •   
  • 在属于类模板的成员规范但不是朋友声明的成员声明中,id-expression为   一个类名,用于命名当前实例化   立即封闭类模板;或
  •   
  • 在名称空间范围的声明中或在朋友声明中,id-expression是限定构造函数的合格ID   ([class.qual])。
  •   
     

类名称不得为typedef名称。在构造函数中   声明,可选decl-specifier-seq中的每个decl-specifier   应该是friend,inline,explicit或constexpr。

正如我在强调的部分中所看到的,ptr-declarator仅必须是一个id表达式。或者用更简单,更不准确的术语来说,它必须只是类名。

那么,为什么要在Clang和GCC中添加星号?看来他们有一个错误,并且这里没有在ptr-declarator上应用语义约束。这些限制很重要,因为纯语法允许带有星号。它位于[dcl.decl]/4中(仅部分复制):

  

声明符具有语法

ptr-declarator:
    noptr-declarator
    ptr-operator ptr-declarator

ptr-operator:
    * attribute-specifier-seqopt cv-qualifier-seqopt
    & attribute-specifier-seqopt
    && attribute-specifier-seqopt
    nested-name-specifier * attribute-specifier-seqopt cv-qualifier-seqopt

看到语法的ptr-operator了吗?就是说*可以出现在您放置它的位置。或&甚至&&。但是声明中的语义(我首先引用的段落)使其成为非法。

所以必须得出结论,这是GCC和Clang中的错误。