
The difference from the previous try is that we no longer directly access function declarations from position independent executables. It should work, but currently doesn't with some linkers. It now includes a fix to not mark available_externally definitions as dso_local. Original message: Start setting dso_local in clang. This starts adding dso_local to clang. The hope is to eventually have TargetMachine::shouldAssumeDsoLocal go away. My objective for now is to move enough of it to clang to remove the need for the TargetMachine one to handle PIE copy relocations and -fno-plt. With that it should then be easy to implement a -fno-copy-reloc in clang. This patch just adds the cases where we assume a symbol to be local based on the file being compiled for an executable or a shared library. llvm-svn: 324535
157 lines
5.6 KiB
C++
157 lines
5.6 KiB
C++
// RUN: %clangxx -target x86_64-unknown-unknown -g %s -emit-llvm -S -o - | FileCheck %s
|
|
// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++98 %s -emit-llvm -S -o - | FileCheck %s
|
|
// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck %s
|
|
// PR14471
|
|
|
|
// CHECK: @_ZN1C1aE = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]]
|
|
// CHECK: @_ZN1C1bE = dso_local global i32 2, align 4, !dbg [[B:![0-9]+]]
|
|
// CHECK: @_ZN1C1cE = dso_local global i32 1, align 4, !dbg [[C:![0-9]+]]
|
|
|
|
enum X {
|
|
Y
|
|
};
|
|
class C
|
|
{
|
|
static int a;
|
|
const static bool const_a = true;
|
|
protected:
|
|
static int b;
|
|
#if __cplusplus >= 201103L
|
|
constexpr static float const_b = 3.14;
|
|
#else
|
|
const static float const_b = 3.14;
|
|
#endif
|
|
public:
|
|
static int c;
|
|
const static int const_c = 18;
|
|
int d;
|
|
static X x_a;
|
|
};
|
|
|
|
// The definition of C::a drives the emission of class C, which is
|
|
// why the definition of "a" comes before the declarations while
|
|
// "b" and "c" come after.
|
|
|
|
// CHECK: [[A]] = !DIGlobalVariableExpression(var: [[AV:.*]], expr: !DIExpression())
|
|
// CHECK: [[AV]] = distinct !DIGlobalVariable(name: "a",
|
|
// CHECK-SAME: declaration: ![[DECL_A:[0-9]+]])
|
|
//
|
|
// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}}, identifier: "_ZTS1X")
|
|
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct"
|
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var"
|
|
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "static_decl_templ<int>"
|
|
// CHECK-NOT: DIFlagFwdDecl
|
|
// CHECK-SAME: ){{$}}
|
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var"
|
|
|
|
int C::a = 4;
|
|
// CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BV:.*]], expr: !DIExpression())
|
|
// CHECK: [[BV]] = distinct !DIGlobalVariable(name: "b",
|
|
// CHECK-SAME: declaration: ![[DECL_B:[0-9]+]])
|
|
// CHECK: ![[DECL_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b"
|
|
// CHECK-NOT: size:
|
|
// CHECK-NOT: align:
|
|
// CHECK-NOT: offset:
|
|
// CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember)
|
|
//
|
|
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C")
|
|
//
|
|
// CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a"
|
|
// CHECK-NOT: size:
|
|
// CHECK-NOT: align:
|
|
// CHECK-NOT: offset:
|
|
// CHECK-SAME: flags: DIFlagStaticMember)
|
|
//
|
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a"
|
|
// CHECK-NOT: size:
|
|
// CHECK-NOT: align:
|
|
// CHECK-NOT: offset:
|
|
// CHECK-SAME: flags: DIFlagStaticMember,
|
|
// CHECK-SAME: extraData: i1 true)
|
|
|
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b"
|
|
// CHECK-NOT: size:
|
|
// CHECK-NOT: align:
|
|
// CHECK-NOT: offset:
|
|
// CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember,
|
|
// CHECK-SAME: extraData: float 0x{{.*}})
|
|
|
|
// CHECK: ![[DECL_C:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "c"
|
|
// CHECK-NOT: size:
|
|
// CHECK-NOT: align:
|
|
// CHECK-NOT: offset:
|
|
// CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember)
|
|
//
|
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_c"
|
|
// CHECK-NOT: size:
|
|
// CHECK-NOT: align:
|
|
// CHECK-NOT: offset:
|
|
// CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember,
|
|
// CHECK-SAME: extraData: i32 18)
|
|
//
|
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a"
|
|
// CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember)
|
|
|
|
int C::b = 2;
|
|
// CHECK: [[C]] = !DIGlobalVariableExpression(var: [[CV:.*]], expr: !DIExpression())
|
|
// CHECK: [[CV]] = distinct !DIGlobalVariable(name: "c", {{.*}} declaration: ![[DECL_C]])
|
|
int C::c = 1;
|
|
|
|
int main()
|
|
{
|
|
C instance_C;
|
|
instance_C.d = 8;
|
|
return C::c;
|
|
}
|
|
|
|
// CHECK-NOT: !DIGlobalVariable(name: "anon_static_decl_var"
|
|
|
|
// Test this in an anonymous namespace to ensure the type is retained even when
|
|
// it doesn't get automatically retained by the string type reference machinery.
|
|
namespace {
|
|
struct anon_static_decl_struct {
|
|
static const int anon_static_decl_var = 117;
|
|
};
|
|
}
|
|
|
|
|
|
int ref() {
|
|
return anon_static_decl_struct::anon_static_decl_var;
|
|
}
|
|
|
|
template<typename T>
|
|
struct static_decl_templ {
|
|
static const int static_decl_templ_var = 7;
|
|
};
|
|
|
|
template<typename T>
|
|
const int static_decl_templ<T>::static_decl_templ_var;
|
|
|
|
int static_decl_templ_ref() {
|
|
return static_decl_templ<int>::static_decl_templ_var;
|
|
}
|
|
|
|
// Verify that even when a static member declaration is created lazily when
|
|
// creating the definition, the declaration line is that of the canonical
|
|
// declaration, not the definition. Also, since we look at the canonical
|
|
// definition, we should also correctly emit the constant value (42) into the
|
|
// debug info.
|
|
struct V {
|
|
virtual ~V(); // cause the definition of 'V' to be omitted by no-standalone-debug optimization
|
|
static const int const_va = 42;
|
|
};
|
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_va",
|
|
// CHECK-SAME: line: [[@LINE-3]]
|
|
// CHECK-SAME: extraData: i32 42
|
|
const int V::const_va;
|
|
|
|
namespace x {
|
|
struct y {
|
|
// CHECK: !DIGlobalVariable(name: "z",
|
|
// CHECK-SAME: scope: [[NS_X:![0-9]+]]
|
|
// CHECK: [[NS_X]] = !DINamespace(name: "x"
|
|
static int z;
|
|
};
|
|
int y::z;
|
|
}
|