Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / compilerplugins / clang / faileddyncast.cxx
blobf99077137f9f3392654e0092fa298106f91271e7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <algorithm>
12 #include "clang/AST/Attr.h"
13 #include "clang/AST/CXXInheritance.h"
15 #include "plugin.hxx"
17 namespace {
19 // cf. Clang's clang::AST::CXXDynamicCastExpr::isAlwaysNull
20 // (lib/AST/ExprCXX.cpp):
21 bool isAlwaysNull(CXXDynamicCastExpr const * expr) {
22 QualType SrcType = expr->getSubExpr()->getType();
23 QualType DestType = expr->getType();
25 if (const clang::PointerType *SrcPTy = SrcType->getAs<clang::PointerType>()) {
26 SrcType = SrcPTy->getPointeeType();
27 #if 0
28 DestType = DestType->castAs<PointerType>()->getPointeeType();
29 #else
30 auto DstPTy = DestType->getAs<clang::PointerType>();
31 if (!DstPTy)
32 return false;
33 DestType = DstPTy->getPointeeType();
34 #endif
37 if (DestType->isVoidType())
38 return false;
40 #if 0
41 const CXXRecordDecl *SrcRD =
42 cast<CXXRecordDecl>(SrcType->castAs<RecordType>()->getDecl());
43 #else
44 auto SrcRT = SrcType->getAs<RecordType>();
45 if (!SrcRT)
46 return false;
47 const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(SrcRT->getDecl());
48 #endif
50 #if 0
51 if (!SrcRD->hasAttr<FinalAttr>())
52 return false;
53 #endif
55 #if 0
56 const CXXRecordDecl *DestRD =
57 cast<CXXRecordDecl>(DestType->castAs<RecordType>()->getDecl());
58 #else
59 auto DestRT = DestType->getAs<RecordType>();
60 if (!DestRT)
61 return false;
62 const CXXRecordDecl *DestRD = cast<CXXRecordDecl>(DestRT->getDecl());
63 #endif
65 #if 1
66 if (!(SrcRD && DestRD))
67 return false;
69 if (DestRD->hasAttr<FinalAttr>()) {
70 CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
71 /*DetectVirtual=*/false);
72 if (DestRD->isDerivedFrom(SrcRD, Paths) &&
73 std::all_of(Paths.begin(), Paths.end(),
74 [](CXXBasePath const & Path) {
75 return Path.Access != AS_public; }))
76 return true;
79 if (!SrcRD->hasAttr<FinalAttr>())
80 return false;
81 #endif
83 #if 0
84 return !DestRD->isDerivedFrom(SrcRD);
85 #else
86 return !(DestRD->isDerivedFrom(SrcRD)
87 || SrcRD->isDerivedFrom(DestRD)
88 || SrcRD == DestRD);
89 #endif
92 class FailedDynCast:
93 public RecursiveASTVisitor<FailedDynCast>, public loplugin::Plugin
95 public:
96 explicit FailedDynCast(loplugin::InstantiationData const & data):
97 Plugin(data) {}
99 bool shouldVisitTemplateInstantiations() const { return true; }
101 void run() override;
103 bool VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr);
106 void FailedDynCast::run() {
107 if (compiler.getLangOpts().CPlusPlus) {
108 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
112 bool FailedDynCast::VisitCXXDynamicCastExpr(CXXDynamicCastExpr const * expr) {
113 if (ignoreLocation(expr)) {
114 return true;
116 if (isAlwaysNull(expr)) {
117 report(
118 DiagnosticsEngine::Warning,
119 "dynamic_cast from %0 to %1 always fails", expr->getLocStart())
120 << expr->getSubExpr()->getType() << expr->getType()
121 << expr->getSourceRange();
123 return true;
126 loplugin::Plugin::Registration<FailedDynCast> X("faileddyncast");
130 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */