Remove exec bits from docx
[LibreOffice.git] / compilerplugins / clang / stringviewdangle.cxx
blob99cb852d03b6762149de90631b25ced3c8fcd84d
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 */
9 #ifndef LO_CLANG_SHARED_PLUGINS
11 #include <cassert>
12 #include <string>
13 #include <iostream>
14 #include <unordered_map>
15 #include <unordered_set>
17 #include "plugin.hxx"
18 #include "check.hxx"
19 #include "compat.hxx"
20 #include "config_clang.h"
21 #include "clang/AST/CXXInheritance.h"
22 #include "clang/AST/StmtVisitor.h"
24 /**
25 Look for places where we are assigning a temporary O[U]String to a std::*string_view, which leads
26 to a view pointing to freed memory.
29 namespace
31 class StringViewDangle : public loplugin::FilteringPlugin<StringViewDangle>
33 public:
34 explicit StringViewDangle(loplugin::InstantiationData const& data)
35 : FilteringPlugin(data)
39 bool preRun() override { return true; }
41 virtual void run() override
43 if (!preRun())
44 return;
45 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
48 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const*);
49 bool VisitVarDecl(VarDecl const*);
52 static const Expr* IgnoreImplicitAndConversionOperator(const Expr* expr)
54 expr = expr->IgnoreImplicit();
55 if (auto memberCall = dyn_cast<CXXMemberCallExpr>(expr))
57 if (auto conversionDecl = dyn_cast_or_null<CXXConversionDecl>(memberCall->getMethodDecl()))
59 if (!conversionDecl->isExplicit())
60 expr = memberCall->getImplicitObjectArgument()->IgnoreImpCasts();
63 return expr;
66 bool StringViewDangle::VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* cxxOperatorCallExpr)
68 if (ignoreLocation(cxxOperatorCallExpr))
69 return true;
71 auto op = cxxOperatorCallExpr->getOperator();
72 if (op != OO_Equal)
73 return true;
74 if (!loplugin::TypeCheck(cxxOperatorCallExpr->getType())
75 .ClassOrStruct("basic_string_view")
76 .StdNamespace())
77 return true;
78 auto expr = IgnoreImplicitAndConversionOperator(cxxOperatorCallExpr->getArg(1));
79 auto tc = loplugin::TypeCheck(expr->getType());
80 if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace()
81 && !tc.Class("OString").Namespace("rtl").GlobalNamespace())
82 return true;
83 if (!isa<MaterializeTemporaryExpr>(expr))
84 return true;
85 report(DiagnosticsEngine::Warning, "view pointing into temporary i.e. dangling",
86 cxxOperatorCallExpr->getExprLoc())
87 << cxxOperatorCallExpr->getSourceRange();
88 return true;
91 bool StringViewDangle::VisitVarDecl(VarDecl const* varDecl)
93 if (ignoreLocation(varDecl))
94 return true;
95 if (!loplugin::TypeCheck(varDecl->getType()).ClassOrStruct("basic_string_view").StdNamespace())
96 return true;
97 if (!varDecl->hasInit())
98 return true;
99 auto expr = IgnoreImplicitAndConversionOperator(varDecl->getInit());
100 auto tc = loplugin::TypeCheck(expr->getType());
101 if (!tc.Class("OUString").Namespace("rtl").GlobalNamespace()
102 && !tc.Class("OString").Namespace("rtl").GlobalNamespace())
103 return true;
104 if (!isa<MaterializeTemporaryExpr>(expr))
105 return true;
106 report(DiagnosticsEngine::Warning, "view pointing into temporary i.e. dangling",
107 varDecl->getLocation())
108 << varDecl->getSourceRange();
109 return true;
112 loplugin::Plugin::Registration<StringViewDangle> stringviewdangle("stringviewdangle");
115 #endif // LO_CLANG_SHARED_PLUGINS
117 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */