oracle的编译器,编译器 - Oracle Solaris Studio 12.3 发行版的新增功能

编译器

本节介绍了此发行版中编译器的已知问题、问题和解决方法。

编译器共有的问题

文档勘误表

下面列出了已发布编译器文档中的错误。

cc(1)、CC(1) 和f95(1) 手册页没有列出 —xarch=sse3a 标志,此标志会将 AMD 指令集(包括 3dnow)添加到 SSE3 指令集中。

C 和 C++ 文档没有指明—xMF 选项只可用于 —xMD 或—xMMD,而不可用于 —xM 或 —xM1。如果指定,它会覆盖用于这些选项的缺省 .d 文件名称。

C++

Solaris 上的 Apache 标准库问题

安装在 Solaris 10u10 和更早版本以及 Solaris 11 最初发行版中的 Apache stdcxx 库在头文件 stdcxx4/loc/_moneypunct.h 中有语法错误。早期版本的编译器没有发现此错误,但

Oracle Solaris Studio 12.3 C++ 编译器发现了此错误。无法禁用错误检测。

对此错误的修复在 Solaris 10 的修补程序和首个 Solaris 11 SRU 中提供。Solaris 10u11 和 Solaris 11u1

推出时将包含此修复。

多义性:构造函数调用或指向函数的指针

某些 C++ 语句有可能解释成声明或者表达式语句。C++ 消除歧义规则为:如果一个语句可以处理成声明,那么它就是声明。

早期版本的编译器会错误解释类似于下面的代码:struct S {

S();

};

struct T {

T( const S& );

};

T v( S() ); // ???

编程人员也许本来打算在最后一行定义变量 v,并且用类型为 S 的临时变量对它进行初始化。早期版本的编译器会这样解释这条语句。

但是在声明环境里,构造符号 "S()" 也可以是抽象声明符(不带标识符),表示“没有返回值类型为 S 的参数的函数”。在这种情况下,该语句会自动转换为函数指针 "S(*)()"。这样该语句仍可作为函数 v 的声明,该函数有一个函数指针类型的参数,返回类型为 T 的值。

当前版本的编译器可以正确地解释该语句,但这未必是编程人员所需要的结果。

可以使用两种方法来修改上述代码以便不产生歧义:T v1( (S()) ); // v1 is an initialized object

T v2( S(*)() ); // v2 is a function

第一行中另加的圆括号表明它不是 v1 作为函数声明的有效语法,所以它的唯一可能解释是“利用类型为S 的临时值进行初始化的类型为T 的目标”。

同样,构造符号 "S(*)()" 不可能是一个值,所以它的唯一可能解释是函数声明。

第一行也可以改写为:

T v1 = S();

虽然这时语句含义非常清楚,但这种形式的初始化有时会创建一个额外的临时变量,而一般情况下不会发生这种情况。

建议不要编写与下面语句类似的代码,因为它的含义不清楚,不同的编译器可能会提供不同的结果。

T v( S() ); // not recommended

如果将 -xipo 或 -xcrossfile 与 -instances=static 组合,链接会失败

模板选项 -instances=static(或 -pto)在与 -xcrossfile 或 -xipo 选项组合时无效。使用该组合的程序会经常发生链接失败。

如果使用 -xcrossfile 或 -xipo 选项,请使用缺省的模板编译模型 -instances=global 进行替代。

通常,不要使用 -instances=static(或 -pto)。它不再有任何优点,此外,C++ 用户指南中还对其缺点进行了说明。

名称改编链接问题

以下情况会导致链接问题。

函数在一个地方声明带有一个 const 参数,而在另一个地方又声明带有一个非 const 参数。

示例:void foo1(const int);

void foo1(int);

这两个声明是等效的,但编译器会将其改编为两个不同的名称。要避免这个问题,则不应将值参数声明为 const。例如,在任何位置都使用 void foo1(int),包括该函数定义体。

函数有两个具有相同复合类型的参数,但只有一个参数是用 typedef 声明的。

示例:class T;

typedef T x;

// foo2 has composite (that is, pointer or array)

// parameter types

void foo2(T*, T*);

void foo2(T*, x*);

void foo2(x*, T*);

void foo2(x*, x*);

所有的 foo2 声明都是等效的,并且应该改编相同的名称。但是,编译器只会改编部分声明的名称。为了避免这个问题,应该统一使用 typedef。

如果您无法统一使用 typedef,解决方法是:在定义该函数的文件中使用弱符号,使得声明与函数的定义一致。例如:#pragma weak "__1_undefined_name" = "__1_defined_name"

请注意,某些改编名称依赖于目标体系结构。(例如,在 SPARC V9 体系结构 (-m64) 中,size_t 是 unsigned long,而在其他体系结构中是 signed int。)在这种情况下,会出现两个版本的改编名称,分别对应两个模式。这时必须使用两个 pragma,并用适当的 #if 指令对其进行控制。

不支持引用模板中的非全局名称空间目标

如果您使用 -instances=extern 编译,则使用模板和静态对象的程序会出现未定义符号的链接时错误。使用缺省设置 -instances=global 则不会出现问题。编译器不支持对模板中的非全局名称空间作用域目标的引用。请看以下示例:static int k;

template class C {

T foo(T t) { ... k ... }

};

在本示例中,一个模板类的成员引用了静态名称空间作用域的变量。请记住,名称空间作用域包含文件作用域。编译器不支持模板类的成员引用静态名称空间作用域的变量。另外,如果模板在其他的编译单元实例化,那么每个实例都会指向不同的 k,这破坏了 C++ 一次定义规则,代码的行为将会不可预测。

下面的方法也是可行的,但这取决于您如何使用 k,以及它应有的功能。第二个选项仅可供属于类成员的函数模板使用。

可以为变量提供外部链接属性:int k; // not static

所有的实例都使用同一个 k。

也可以使这个变量成为类的静态成员:template class C {

static int k;

T foo(T t) { ... k ... }

};

静态类成员具有外部链接属性。每个 C::foo 的实例都使用不同的 k。而 C::k 的一个实例可以被其他函数共享。此选项可能是您需要的选项。

名称空间内的 #pragma align 需要改编名称

在名称空间内使用 #pragma align 时,必须使用改编名称。例如,在下面的代码中,#pragma align 语句是无效的。要更正此问题,应将 #pragma align 语句中的 a, b 和 c 替换为其改编名称。namespace foo {

#pragma align 8 (a, b, c) // has no effect

//use mangled names: #pragma align 8 (__1cDfooBa_, __1cDfooBb_, __1cDfooBc_)

static char a;

static char b;

static char c;

}

Fortran

在此 f95 编译器发行版中应注意以下问题:

不换行打印行末尾之前的空格不会影响输出位置 (7087522)。

输出语句格式末尾的 X 编辑描述符不会影响输出记录中后续字符的位置。如果输出语句中有 ADVANCE='NO' 并且有更多字符要通过后续输出语句传送到同一记录,则会导致差异。

在很多情况下,可以通过添加空白字符串编辑描述符,而不是 nX 编辑描述符来解决此问题。它们并不完全相同,因为空白字符串编辑描述符实际上会将空白字符包含在记录中,而 nX 仅跳过后 n 个字符,缺省情况下通常导致跳过的位置中产生空白。

一行中有两个连续 & 号的有效代码会被拒绝 (7035243)。

Fortran 标准禁止有一个 & 号的空续行。但是,仍可以创建同一行中有两个 & 号的空续行,这不在标准限制范围之内。编译器不会处理这种情况,而会显示一条错误消息。解决方法是删除该行,这只会影响程序可读性而并不添加任何语义。

BOZ 常量有时会被截断 (6944225)。

在某些相对更复杂的情况下,如数组构造,BOZ 常量可能会被截成 4 个字节的缺省整数大小,即使它所应指定给的相应项是一个 8 个字节的整数实体。解决方法是在数组构造中使用正确类型和种类的常量,而不要使用 BOZ 常量。

Fortran 编译器的早期发行版引入了某些不兼容性,并被此编译器发行版所继承,如果您是从 Fortran 编译器早期发行版进行更新,应注意这一点。请注意下面的不兼容性:

Fortran 77 库已删除

需注意 Oracle Solaris Studio 12.2 发行版已删除了废弃的 FORTRAN 77 库。这意味着使用依赖于共享库 libF77、libM77 和libFposix 的传统

Sun WorkShop f77 编译器编译的旧的可执行文件将不会运行。

数组内部函数使用全局寄存器:

数组内部函数 ANY, ALL, COUNT, MAXVAL, MINVAL, SUM, PRODUCT、DOT_PRODUCT 和 MATMUL 针对相应 SPARC 平台体系结构进行了高度优化。因此,它们使用全局寄存器 %g2, %g3 和 %g4 作为临时寄存器。

如果调用了上述所列的数组内在函数,则用户代码不应该认为这些寄存器可用于暂时存储。当调用数组内在函数时,这些寄存器中的数据将被覆盖。

归档库中的 F95 模块不包括在可执行文件中:

调试器 dbx 要求编译中使用的所有对象文件都包含在可执行文件中。通常,无需用户执行额外操作,程序即可满足此要求。但使用含有模块的归档文件时例外。如果程序使用了一个模块,但没有引用模块中的任何过程或变量,则产生的对象文件不会包含对模块中定义的符号的引用。只有对目标文件中定义的符号具有引用时,链接器才会链接归档文件中的对象文件。如果不存在此类引用,对象文件将不包括在可执行文件中。当 dbx 尝试查找与使用的模块相关联的调试信息时,将发出警告。对于缺少调试信息的符号,则无法提供有关这些符号的信息。

使用 -u 链接程序选项可以解决这个问题。此选项使用一个符号作为其选项参数。它会将该符号添加到未定义的链接程序符号集中,这就需要解析此符号。与模块关联的链接程序符号通常是模块名称,其所有字母均为小写,后面跟有一条下划线。

例如,为了强制包含模块 MODULE_1 的对象文件被归档文件采用,请指定链接程序选项 -u module_1_。如果使用 f95 命令进行链接,请在命令行上使用 -Qoption ld -umodule_1_。

Linux 平台上的 gethrtime(3F)

启用系统节能功能时,没有可靠方式可以精确地获得 AMD 处理器上的时钟速率。因此,使用基于 gethrtime(3F) 的计时函数(Fortran 编译器的 Linux 版 Solaris gethrtime(3C) 函数)在 Linux

平台上获得高精度实际时间的方法只有在禁用了节能功能的 AMD 系统才会精确。要禁用节能功能,可能需要重新引导系统。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值