Stephan Bergmann 2157160b26 Recursively include unnamed inner classes in "layout heuristic"
This covers both cases where the inner class is defined in the declaration of a
non-static data member, as needed by clang-cl for

> bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx(799,19): error: unused class member [loplugin:unusedmember]
>             PVOID pExceptionObject;
>             ~~~~~~^~~~~~~~~~~~~~~~
> bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx(801,19): error: unused class member [loplugin:unusedmember]
>             PVOID pThrowImageBase;
>             ~~~~~~^~~~~~~~~~~~~~~

as well as anonymous structs (even if there appears to be no need for that
across the LO code base; they are part of C11 and a widely supported C++
extension).

The newly added TODO will eventually need fixing, but I didn't find a way in
Clang to tell whether a RecordDecl is defined as part of a FieldDecl, and the
issue appears to be of no practical relevance for the current LO code base.

Change-Id: I08cecddb9b4a70c3ca480d2d2ab1ea4f198011b2
Reviewed-on: https://gerrit.libreoffice.org/84967
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2019-12-11 19:51:31 +01:00

219 lines
3.2 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace Enum
{
namespace
{
struct S
{
enum E
{
E1,
E2
};
E e;
};
}
void f(S s) { (void)s.e; }
}
namespace ElaboratedEnum
{
namespace
{
struct S
{
S()
{
enum E1 e1 = E11;
(void)e1;
}
enum E1
{
E11,
E12
};
enum E2
{
E21,
E22
};
enum E2 e2;
};
}
void f()
{
S s;
(void)s;
(void)s.e2;
}
}
namespace UnusedEnum
{
namespace
{
struct S
{
enum E // expected-error {{unused class member [loplugin:unusedmember]}}
{
E1,
E2
};
};
}
void f() { (void)S::E1; }
}
namespace UnusedDataMember
{
namespace
{
struct NT
{
NT(int = 0) {}
~NT() {}
};
struct __attribute__((warn_unused)) T
{
T(int = 0) {}
~T() {}
};
struct S
{
int i1;
int i2; // expected-error {{unused class member [loplugin:unusedmember]}}
int const& i3; // expected-error {{unused class member [loplugin:unusedmember]}}
NT nt;
T t1;
T t2; // expected-error {{unused class member [loplugin:unusedmember]}}
T const& t3; // expected-error {{unused class member [loplugin:unusedmember]}}
S()
: i1(0)
, i3(i1)
, t1(0)
, t3(t1)
{
(void)i1;
(void)t1;
}
};
}
void f()
{
S s;
(void)s;
}
}
namespace Alignof
{
namespace
{
struct S
{
int i;
};
}
void f() { (void)alignof(S const(&)[][10]); }
}
namespace Aligned
{
namespace
{
struct S1
{
int i;
};
struct S2
{
int i __attribute__((aligned(__alignof__(S1))));
};
}
void f()
{
S2 s;
s.i = 0;
}
}
namespace Bases
{
namespace
{
struct S1
{
int i1;
};
struct S2 : S1
{
int i2;
};
struct S3 : S2
{
};
}
void f() { (void)sizeof(S3); }
}
namespace Unnamed
{
namespace
{
struct S
{
struct
{
struct
{
int i;
} s2;
struct // anonymous struct extension (widely supported)
{
int j;
};
int k;
} s1;
#if false //TODO: see corresponding TODO in compilerplugins/clang/unusedmember.cxx
static constexpr struct
{
int l; // expected-error {{unused class member [loplugin:unusedmember]}}
} s = {};
#endif
typedef struct
{
int m; // expected-error {{unused class member [loplugin:unusedmember]}}
} t; // expected-error {{unused class member [loplugin:unusedmember]}}
};
}
void f()
{
(void)sizeof(S);
#if false //TODO: see corresponding TODO in compilerplugins/clang/unusedmember.cxx
(void)S::s; // avoid "unused variable 's'" (non-loplugin) warning
#endif
}
}
int main()
{
(void)&Enum::f;
(void)&ElaboratedEnum::f;
(void)&UnusedEnum::f;
(void)&UnusedDataMember::f;
(void)&Alignof::f;
(void)&Aligned::f;
(void)&Bases::f;
(void)&Unnamed::f;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */