我注意到g++有点过于严格的抱怨crossed initialization,我想知道为什么这些误报错误只能通过在编译时查看程序的SSA形式来消除.
让我举一个非常简单的例子:
#include <cstdlib>
int main ()
{
goto end;
int i = 0; // unused variable declaration
end:
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
使用g++ -Wall -Wextra -o example1 example1.cc(g++4.8.1)编译时,编译器会给出以下错误消息:
example1.cc: In function ‘int main()’:
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive]
end:
^
example1.cc:6:8: error: from here [-fpermissive]
goto end;
^
example1.cc:8:7: error: crosses initialization of ‘int i’
int i = 0;
^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable]
Run Code Online (Sandbox Code Playgroud)
因此,它会引发一个实际没有风险的错误,因为该变量未被使用(编译器显然同时具有这两个信息,并且不能将它组合起来推断错误是误报).
更奇怪的是,我希望LLVM在分析程序方面更有效率.所以,我尝试clang++ …
关于此主题的先前问题:
这是我最近提出的问题的后续跟进: clang:没有外线虚拟方法定义(纯抽象C++类) ,并且被标记为此问题的副本:clang的-Wweak-含义是什么?虚函数表?.我不认为那回答了我的问题,所以在这里我专注于困扰我的事情,但尚未得到回答.
我的情景:
我正在尝试使用Clang-3.5编译以下简单的C++代码:
test.h:
class A
{
public:
A();
virtual ~A() = 0;
};
Run Code Online (Sandbox Code Playgroud)
test.cc
#include "test.h"
A::A() {;}
A::~A() {;}
Run Code Online (Sandbox Code Playgroud)
我用来编译它的命令(Linux,uname -r:3.16.0-4-amd64):
$clang-3.5 -Wweak-vtables -std=c++11 -c test.cc
Run Code Online (Sandbox Code Playgroud)
而我得到的错误:
./test.h:1:7: warning: 'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit [-Wweak-vtables]
Run Code Online (Sandbox Code Playgroud)
当A类不是纯抽象时,上面的代码构建得很好.以下代码不会发出警告,唯一的变化是A类不再是抽象的:
test2.h:
class A
{
public:
A();
virtual ~A();
};
Run Code Online (Sandbox Code Playgroud)
test2.cc
#include "test2.h"
A::A() {;}
A::~A() {;}
Run Code Online (Sandbox Code Playgroud)
我的问题
上面的代码在Clang中触发警告的纯抽象类有什么特别之处?
这是一个示例代码:
#include <iostream>
#include <stdexcept>
#include <cstring>
#include <ctime>
#include <sstream>
using std::cout;
using std::endl;
std::size_t const BUF_SIZE(1000);
std::ostream& operator<<(std::ostream& os, std::tm const& rhs)
{
os << asctime(&rhs);
return os;
}
std::istream& operator>>(std::istream& is, std::tm& rhs)
{
while (is.peek() == ' ' || is.peek() == '\t')
{
is.get();
}
std::streampos curPos = is.tellg();
char buf[BUF_SIZE];
is.getline(buf, BUF_SIZE);
char* ptr = strptime(buf, "%D %T", &rhs);
if (ptr == 0)
{
throw std::runtime_error("strptime() failed!");
}
std::size_t processed = ptr - buf;
is.seekg(curPos …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用clang++冲突的命名空间来编译我的C++代码,但不断收到此错误.我的main.cpp文件是一个简单的Hello World程序(用于调试).
我有一种感觉问题是我在我的集群上编译的GCC或clang版本.关于如何追踪这个问题的任何想法?或者排除故障的步骤?
[aebrenne@hpc src]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/data/apps/gcc/4.8.1/libexec/gcc/x86_64-unknown-linux-gnu/4.8.1/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ./configure --with-gmp=/data/apps/gmp/5.1.2 --with-mpfr=/data/apps/mpfr/3.1.2 --with-mpc=/data/apps/mpc-1.0.1 --enable-threads=posix --with-as=/data/apps/binutils/2.23.2/bin/as --mandir=/data/apps/gcc/4.8.1/man --pdfdir=/data/apps/gcc/4.8.1/pdf --htmldir=/data/apps/gcc/4.8.1/html --enable-languages=c,c++,fortran,ada,go,java,lto,objc,obj-c++ --prefix=/data/apps/gcc/4.8.1
Thread model: posix
gcc version 4.8.1 (GCC)
[aebrenne@hpc src]$ clang++ --version
clang version 3.4 (trunk 193367)
Target: x86_64-unknown-linux-gnu
Thread model: posix
[aebrenne@hpc src]$
[aebrenne@hpc src]$ cat main.cpp
#include <iostream>
int main() {
std::cout << "Starting test..." << std::endl;
return 0;
}
[aebrenne@hpc src]$ clang++ -std=c++11 -Wall -g -I/data/apps/gcc/4.8.1/include/c++/4.8.1 main.cpp
In file …Run Code Online (Sandbox Code Playgroud) 我有模板模板参数和clang的问题(可能是我的).以下玩具示例在g ++ 4.7.0下编译并运行,而不是clang ++ 3.0(基于LLVM 3.0),都是ubuntu 12.04.
玩具示例(test_1.cpp):
#include <iostream>
#include <memory>
struct AFn
{
void operator()()
{
; // do something
}
};
template<typename T>
struct impl
{
T *backpointer_;
};
template<typename S, template <typename> class T>
struct implT
{
T<S> *backpointer_;
};
template<typename>
class AClass;
template<>
struct implT<AFn, AClass>
{
implT(std::string message) :
message_(message)
{}
void operator()()
{
std::cout << " : " << message_ << std::endl;
}
std::string message_;
};
template<typename Fn>
class AClass
{
private:
std::shared_ptr<implT<Fn, …Run Code Online (Sandbox Code Playgroud) 在使用g ++的linux上,如果我设置了utf8全局语言环境,那么wcin正确地将UTF-8转码为内部wchar_t编码.
但是,如果我使用经典语言环境并将UTF8语言环境灌输到wcin中,则不会发生这种情况.输入完全失败,或者每个字节独立转换为wchar_t.
使用clang ++和libc ++,既不设置全局语言环境也不设置语言环境wcin.
#include <iostream>
#include <locale>
#include <string>
using namespace std;
int main() {
if(true)
// this works with g++, but not with clang++/libc++
locale::global(locale("C.UTF-8"));
else
// this doesn't work with either implementation
wcin.imbue(locale("C.UTF-8"));
wstring s;
wcin >> s;
cout << s.length() << " " << (s == L"áéú");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输入流仅包含áéú字符.(它们是UTF-8,而不是任何单字节编码).
这是符合标准的吗?我不应该单独留下全局区域设置imbue而是使用吗?
是否应将任何描述的行为归类为实施错误?
Clang编译器生成警告编译此代码片段,我无法弄清楚原因.
const int* Get() {
static const int ARRAY[4] = {1, 2, 3, 4};
return &ARRAY[0];
}
const int& Test() {
const auto& p = Get();
return (*p);
}
warning: returning reference to local temporary object [-Wreturn-stack-address]
return (*p);
Run Code Online (Sandbox Code Playgroud)
GCC没有显示此代码的警告.我可以修复这样的片段:const auto p = Get();
但我想知道是否有一些临时对象,问题更深层次
看起来Clang(3.8)和GNU C++(4.9)中模板实例化的规则是不一样的.这是一个例子:
#include <cstddef>
template <bool>
class Assert {
Assert(); // private constructor for Assert<false>
};
template <>
class Assert<true> { // implicit public constructor for Assert<true>
};
template <size_t N>
class A {
};
template <class T, size_t N>
T foo(A<N>) {
return T(N - 1);
}
template <class T>
T foo(A<0>) { // foo is not defined for N=0
Assert<false>();
return T(0);
}
int main(int argc, char **argv) {
foo<int>(A<3>());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个最小的例子显示了一个模板函数,foo它是在一个类型T和一个自然数上推广的 …
我发现以下一段代码:
#include <iostream>
#include <vector>
template <typename T>
struct X : std::false_type {};
template <template <typename> class Y, typename U>
struct X<Y<U>> : std::true_type {};
int main() {
if (X<int>())
std::cout << "wrong\n";
if (X<std::vector<double>>())
std::cout << "correct\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
仅correct在使用g++-7with 编译时打印-std=c++1z.其它版本g++,clang++或者其他std标志不能产生正确的.
这是当前实现的错误,并且此代码不应该打印任何内容,或者是否在C++ 17中发生了变化,这使得此代码按预期工作?
[编辑以显示.cpp和hpp之间的拆分]
// file.hpp
class Base {
public:
virtual ~Base(void);
Base(void);
Base(const Base&) = default;
};
template<typename T>
class Derived: public Base {
public:
Derived(void);
bool func(void);
};
Run Code Online (Sandbox Code Playgroud)
// file.cpp
#include "file.hpp"
Base::~Base(void) {}
Base::Base(void) {}
template<typename T>
bool Derived<T>::func(void) {return true;}
template<typename T>
Derived<T>::Derived(void) {}
// required to avoid linker errors when using `Derived` elsewhere
template class Derived<int>;
Run Code Online (Sandbox Code Playgroud)
最后一行在Clang v8.0中导致以下编译器警告 warning: explicit template instantiation 'Derived<int>' will emit a vtable in every translation unit [-Wweak-template-vtables]
我的理解是,由于Base至少有一种离线虚拟方法,因此此处所有类的vtable都将锚定到此转换单元,因此是LLVM编码标准中的该指南。那么为什么会生成此警告? …