summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/faileddyncast.cxx
blob: 078d5c884b27e46e3e98a2b86b2a010460657e81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * 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/.
 */
#ifndef LO_CLANG_SHARED_PLUGINS

#include <algorithm>

#include "clang/AST/Attr.h"
#include "clang/AST/CXXInheritance.h"

#include "plugin.hxx"

namespace {

// cf. Clang's clang::AST::CXXDynamicCastExpr::isAlwaysNull
// (lib/AST/ExprCXX.cpp):
bool isAlwaysNull(CXXDynamicCastExpr const * expr) {
  QualType SrcType = expr->getSubExpr()->getType();
  QualType DestType = expr->getType();

  if (const clang::PointerType *SrcPTy = SrcType->getAs<clang::PointerType>()) {
    SrcType = SrcPTy->getPointeeType();
#if 0
    DestType = DestType->castAs<PointerType>()->getPointeeType();
#else
    auto DstPTy = DestType->getAs<clang::PointerType>();
    if (!DstPTy)
      return false;
    DestType = DstPTy->getPointeeType();
#endif
  }

  if (DestType->isVoidType())
    return false;

#if 0
  const CXXRecordDecl *SrcRD =
    cast<CXXRecordDecl>(SrcType->castAs<RecordType>()->getDecl());
#else
  auto SrcRT = SrcType->getAs<RecordType>();
  if (!SrcRT)
    return false;
  const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(SrcRT->getDecl());
#endif

#if 0
  if (!SrcRD->hasAttr<FinalAttr>())
    return false;
#endif

#if 0
  const CXXRecordDecl *DestRD =
    cast<CXXRecordDecl>(DestType->castAs<RecordType>()->getDecl());
#else
  auto DestRT = DestType->getAs<RecordType>();
  if (!DestRT)
    return false;
  const CXXRecordDecl *DestRD = cast<CXXRecordDecl>(DestRT->getDecl());
#endif

#if 1
  if (!(SrcRD && DestRD))
    return false;

  if (DestRD->hasAttr<FinalAttr>()) {
    CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
                       /*DetectVirtual=*/false);
    if (DestRD->isDerivedFrom(SrcRD, Paths) &&
        std::all_of(Paths.begin(), Paths.end(),
                    [](CXXBasePath const & Path) {
                        return Path.Access != AS_public; }))
      return true;
  }

  if (!SrcRD->hasAttr<FinalAttr>())
    return false;
#endif

#if 0
  return !DestRD->isDerivedFrom(SrcRD);
#else
  return !(DestRD->isDerivedFrom(SrcRD)
           || SrcRD->isDerivedFrom(DestRD)
           || SrcRD == DestRD);
#endif
}

class FailedDynCast:
    public loplugin::FilteringPlugin<FailedDynCast>
{
public:
    explicit FailedDynCast(loplugin::InstantiationData const & data):
        FilteringPlugin(data) {}

    bool shouldVisitTemplateInstantiations() const { return true; }

    bool preRun() override;
    void run() override;

    bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr);
};

bool FailedDynCast::preRun() {
    return compiler.getLangOpts().CPlusPlus;
}

void FailedDynCast::run() {
    if (preRun()) {
        TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
    }
}

bool FailedDynCast::VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr) {
    if (ignoreLocation(expr)) {
        return true;
    }
    if (isAlwaysNull(expr)) {
        report(
            DiagnosticsEngine::Warning,
            "dynamic_cast from %0 to %1 always fails", expr->getBeginLoc())
            << expr->getSubExpr()->getType() << expr->getType()
            << expr->getSourceRange();
    }
    return true;
}

loplugin::Plugin::Registration<FailedDynCast> faileddyncast("faileddyncast");

} // namespace

#endif // LO_CLANG_SHARED_PLUGINS

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
6-05-16 07:24:23 +0000'>2016-05-16tdf#87938 libcmis: Google 2FA implementationSzymon Kłos 2016-05-02Related tdf#98416 Libcmis: add a patch to fix Google Drive loginGiuseppe Castagno 2016-03-05upload libmis 0.5.1David Tardon 2015-11-12Generalize COM_GCC_IS_CLANG -> COM_IS_CLANGStephan Bergmann 2015-07-15cmis: allow http authentication even when password is emptyVasily Melenchuk 2015-07-08tdf#90351: server response does not always contain cmis:baseTypeIdThorsten Behrens 2015-07-08tdf#90351 libcmis: prevent crashAndras Timar 2014-12-15Updated CMIS patches and the makefile for the OneDrive bindingMihai Varga 2014-05-11libcmis: WaE: warning C4101: 'e' : unreferenced local variableThomas Arnhold 2014-03-01libcmis (bundled): add patch with missing definition for HTML_PARSE_RECOVERDouglas Mencken 2013-12-04fdo#62531: checkout failed due to bad import of properties in libcmisCédric Bosdonnat 2013-10-19fdo#70393: move libcmis to a subdir of externalKhaled Hosny