Hans Wennborg dfcb7d6a97 Defer codegen of inline method definitions to the end of current top level declaration
We would previously fail to emit a definition of bar() for the following code:

  struct __declspec(dllexport) S {
    void foo() {
      t->bar();
    }
    struct T {
      void bar() {}
    };
    T *t;
  };

Note that foo() is an exported method, but bar() is not. However, foo() refers
to bar() so we need to emit its definition. We would previously fail to
realise that bar() is used.

By deferring the method definitions until the end of the top level declaration,
we can simply call EmitTopLevelDecl on them and rely on the usual mechanisms
to decide whether the method should be emitted or not.

Differential Revision: http://reviews.llvm.org/D4038

llvm-svn: 210356
2014-06-06 17:36:17 +00:00

28 lines
874 B
C++

// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
// <rdar://problem/8684363>: clang++ not respecting __attribute__((used)) on destructors
struct X0 {
// CHECK: define linkonce_odr {{.*}} @_ZN2X0C1Ev
__attribute__((used)) X0() {}
// CHECK: define linkonce_odr {{.*}} @_ZN2X0D1Ev
__attribute__((used)) ~X0() {}
};
// PR19743: not emitting __attribute__((used)) inline methods in nested classes.
struct X1 {
struct Nested {
// CHECK: define linkonce_odr {{.*}} @_ZN2X16Nested1fEv
void __attribute__((used)) f() {}
};
};
struct X2 {
// We must delay emission of bar() until foo() has had its body parsed,
// otherwise foo() would not be emitted.
void __attribute__((used)) bar() { foo(); }
void foo() { }
// CHECK: define linkonce_odr {{.*}} @_ZN2X23barEv
// CHECK: define linkonce_odr {{.*}} @_ZN2X23fooEv
};