New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
/* -*- 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/.
|
|
|
|
*/
|
|
|
|
|
2019-03-07 14:31:17 +01:00
|
|
|
#ifndef LO_CLANG_SHARED_PLUGINS
|
|
|
|
|
2018-02-23 18:05:03 +01:00
|
|
|
#include <algorithm>
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
#include <cassert>
|
2018-02-23 18:05:03 +01:00
|
|
|
#include <cstddef>
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
#include <set>
|
2018-02-23 18:05:03 +01:00
|
|
|
#include <string>
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
|
|
|
|
#include "plugin.hxx"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
using Bases = std::set<CXXRecordDecl const *>;
|
|
|
|
|
|
|
|
Visibility getTypeVisibility(CXXRecordDecl const * decl) {
|
|
|
|
assert(decl->isThisDeclarationADefinition());
|
|
|
|
if (auto const opt = decl->getExplicitVisibility(
|
|
|
|
NamedDecl::VisibilityForType))
|
|
|
|
{
|
|
|
|
return *opt;
|
|
|
|
}
|
|
|
|
if (auto const opt = decl->getExplicitVisibility(
|
|
|
|
NamedDecl::VisibilityForValue))
|
|
|
|
{
|
|
|
|
return *opt;
|
|
|
|
}
|
|
|
|
auto const vis = decl->getVisibility();
|
|
|
|
return vis == DefaultVisibility && decl->isInAnonymousNamespace()
|
|
|
|
? HiddenVisibility : vis;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether 'decl' is derived from 'base', gathering any 'bases' between
|
|
|
|
// 'decl' and 'base', and whether any of those 'bases' or 'base' are 'hidden'
|
|
|
|
// (i.e., have non-default visibility):
|
|
|
|
bool isDerivedFrom(
|
|
|
|
CXXRecordDecl const * decl, CXXRecordDecl const * base, Bases * bases,
|
|
|
|
bool * hidden)
|
|
|
|
{
|
|
|
|
bool derived = false;
|
|
|
|
for (auto const i: decl->bases()) {
|
|
|
|
auto const bd
|
|
|
|
= (cast<CXXRecordDecl>(i.getType()->getAs<RecordType>()->getDecl())
|
|
|
|
->getDefinition());
|
|
|
|
assert(bd != nullptr);
|
|
|
|
if (bd == base) {
|
|
|
|
*hidden |= getTypeVisibility(base) != DefaultVisibility;
|
|
|
|
derived = true;
|
|
|
|
}
|
|
|
|
else if (bd->isDerivedFrom(base)) {
|
|
|
|
if (bases->insert(bd).second) {
|
|
|
|
auto const d = isDerivedFrom(bd, base, bases, hidden);
|
|
|
|
assert(d);
|
|
|
|
*hidden |= getTypeVisibility(bd) != DefaultVisibility;
|
|
|
|
}
|
|
|
|
derived = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return derived;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef vis(Visibility v) {
|
|
|
|
switch (v) {
|
|
|
|
case HiddenVisibility:
|
|
|
|
return "hidden";
|
|
|
|
case ProtectedVisibility:
|
|
|
|
return "protected";
|
|
|
|
case DefaultVisibility:
|
|
|
|
return "default";
|
|
|
|
default:
|
|
|
|
llvm_unreachable("unknown visibility");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-11 10:45:27 +02:00
|
|
|
class DynCastVisibility final:
|
2019-03-05 16:15:22 +01:00
|
|
|
public loplugin::FilteringPlugin<DynCastVisibility>
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
{
|
|
|
|
public:
|
2017-11-07 11:50:47 +01:00
|
|
|
explicit DynCastVisibility(loplugin::InstantiationData const & data):
|
2019-03-05 16:15:22 +01:00
|
|
|
FilteringPlugin(data) {}
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
|
|
|
|
bool shouldVisitTemplateInstantiations() const { return true; }
|
|
|
|
|
|
|
|
bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr) {
|
|
|
|
if (ignoreLocation(expr)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
auto td = expr->getTypeAsWritten();
|
|
|
|
if (auto const t = td->getAs<ReferenceType>()) {
|
|
|
|
td = t->getPointeeType();
|
|
|
|
}
|
2017-09-11 10:48:12 +02:00
|
|
|
while (auto const t = td->getAs<clang::PointerType>()) {
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
td = t->getPointeeType();
|
|
|
|
}
|
|
|
|
auto const rtd = td->getAs<RecordType>();
|
|
|
|
if (rtd == nullptr) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
auto const rdd = cast<CXXRecordDecl>(rtd->getDecl())->getDefinition();
|
|
|
|
assert(rdd != nullptr);
|
|
|
|
if (getTypeVisibility(rdd) != DefaultVisibility) {
|
2018-02-23 18:05:03 +01:00
|
|
|
// Heuristic to find problematic dynamic_cast<T> with hidden type T is: T is defined in
|
|
|
|
// include/M1/ while the compilation unit is in module M2/ with M1 != M2. There are
|
|
|
|
// legitimate cases where T is a hidden type in dynamic_cast<T>, e.g., when both the
|
|
|
|
// type and the cast are in the same library. This heuristic appears to be conservative
|
|
|
|
// enough to produce only a few false positives (which have been addressed with
|
|
|
|
// preceding commits, marking the relevant types in global include files as
|
|
|
|
// SAL_DLLPUBLIC_RTTI after all, to be on the safe side) and aggressive enough to find
|
|
|
|
// at least some interesting cases (though it would still not be aggressive enough to
|
|
|
|
// have found ff570b4b58dbf274d3094d21d974f18b613e9b4b "DocumentSettingsSerializer must
|
|
|
|
// be SAL_DLLPUBLIC_RTTI for dynamic_cast"):
|
2018-05-29 11:28:07 +02:00
|
|
|
auto const file = getFileNameOfSpellingLoc(
|
2018-02-23 18:05:03 +01:00
|
|
|
compiler.getSourceManager().getSpellingLoc(rdd->getLocation()));
|
|
|
|
if (loplugin::hasPathnamePrefix(file, SRCDIR "/include/")) {
|
|
|
|
std::size_t const n1 = std::strlen(SRCDIR "/include/");
|
|
|
|
std::size_t n2 = file.find('/', n1);
|
|
|
|
#if defined _WIN32
|
|
|
|
n2 = std::min(n2, file.find('\\', n1));
|
|
|
|
#endif
|
|
|
|
auto const seg = n2 >= file.size() ? file.substr(n1) : file.substr(n1, n2 - n1);
|
|
|
|
auto prefix = std::string(SRCDIR "/");
|
|
|
|
prefix += seg;
|
|
|
|
if (!loplugin::hasPathnamePrefix(
|
2018-05-29 11:28:07 +02:00
|
|
|
handler.getMainFileName(), prefix))
|
2018-02-23 18:05:03 +01:00
|
|
|
{
|
|
|
|
report(
|
|
|
|
DiagnosticsEngine::Warning,
|
|
|
|
"Suspicious dynamic_cast to %0 with %1 type visibility", expr->getExprLoc())
|
|
|
|
<< td << vis(getTypeVisibility(rdd)) << expr->getSourceRange();
|
|
|
|
report(DiagnosticsEngine::Note, "class %0 defined here", rdd->getLocation())
|
|
|
|
<< td << rdd->getSourceRange();
|
|
|
|
}
|
|
|
|
}
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
auto ts = expr->getSubExpr()->getType();
|
2017-09-11 10:48:12 +02:00
|
|
|
while (auto const t = ts->getAs<clang::PointerType>()) {
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
ts = t->getPointeeType();
|
|
|
|
}
|
|
|
|
auto const rts = ts->getAs<RecordType>();
|
2017-09-05 09:38:30 +02:00
|
|
|
if (rts == nullptr) { // in case it's a dependent type
|
|
|
|
return true;
|
|
|
|
}
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
auto const rds = cast<CXXRecordDecl>(rts->getDecl())->getDefinition();
|
|
|
|
assert(rds != nullptr);
|
|
|
|
Bases bs;
|
|
|
|
bool hidden = false;
|
|
|
|
if (!(isDerivedFrom(rdd, rds, &bs, &hidden) && hidden)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
report(
|
|
|
|
DiagnosticsEngine::Warning,
|
|
|
|
("dynamic_cast from %0 with %1 type visibility to %2 with %3 type"
|
|
|
|
" visibility"),
|
|
|
|
expr->getExprLoc())
|
|
|
|
<< ts << vis(getTypeVisibility(rds)) << td
|
|
|
|
<< vis(getTypeVisibility(rdd)) << expr->getSourceRange();
|
|
|
|
report(
|
|
|
|
DiagnosticsEngine::Note,
|
|
|
|
"base class %0 with %1 type visibility defined here",
|
|
|
|
rds->getLocation())
|
|
|
|
<< ts << vis(getTypeVisibility(rds)) << rds->getSourceRange();
|
|
|
|
for (auto const i: bs) {
|
|
|
|
if (getTypeVisibility(i) != DefaultVisibility) {
|
|
|
|
report(
|
|
|
|
DiagnosticsEngine::Note,
|
|
|
|
("intermediary class %0 with %1 type visibility defined"
|
|
|
|
" here"),
|
|
|
|
i->getLocation())
|
|
|
|
<< i << vis(getTypeVisibility(i)) << i->getSourceRange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
report(
|
|
|
|
DiagnosticsEngine::Note,
|
|
|
|
"derived class %0 with %1 type visibility defined here",
|
|
|
|
rdd->getLocation())
|
|
|
|
<< td << vis(getTypeVisibility(rdd)) << rdd->getSourceRange();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-07 14:31:17 +01:00
|
|
|
virtual bool preRun() override {
|
|
|
|
return compiler.getLangOpts().CPlusPlus;
|
|
|
|
}
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
private:
|
|
|
|
void run() override {
|
2019-03-07 14:31:17 +01:00
|
|
|
if (preRun()) {
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-03-07 14:31:17 +01:00
|
|
|
static loplugin::Plugin::Registration<DynCastVisibility> dyncastvisibility(
|
2017-10-11 10:45:27 +02:00
|
|
|
"dyncastvisibility");
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-03-07 14:31:17 +01:00
|
|
|
#endif // LO_CLANG_SHARED_PLUGINS
|
|
|
|
|
New loplugin:dyncastvisibility
...to find uses of dynamic_cast where the static (base) type has hidden
visibility while the dynamic (derived) one has default visibility, and which may
thus fail at least on macOS like happened in
d5ed3cd6dbd22bb18542778f1c48f4d5b3ae0f95 "Make WinMtfFontStyle's base class
EMFIO_DLLPUBLIC, too".
libcxxabi's __dynamic_cast takes static_type and dst_type arguments. Now, if
dst_type (the derived type, with default visibility) is taken from .so A (and
thus references the version of the base type info hidden in .so A) but the
__dynamic_cast call is made from .so B, it passes for static_type the base type
information hidden in .so B, and __dynamic_cast will consider the cast to fail.
I'm not sure whether hidden intermediary types (in the hierarchy between the
dynamic_cast's base and derived types) acutally cause a problem too, but lets
flag them with the plugin anyway.
The fixes use SAL_DLLPUBLIC_RTTI. For one, there appear to be no other reasons
than type visibility to make those classes SAL_DLLPUBLIC. For another, this
nicely avoids any actual changes on Windows (where SAL_DLLPUBLIC expands to
nothing, and many of the affected classes were explicityl introduced into class
hierarchies as "MSVC hacks").
Change-Id: Ia85a9635cebffb1009a9efc1484b8bd4025585d4
Reviewed-on: https://gerrit.libreoffice.org/41802
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2017-09-01 20:14:25 +02:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|