1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
9 #ifndef LO_CLANG_SHARED_PLUGINS
14 #include <unordered_map>
15 #include <unordered_set>
20 #include "config_clang.h"
21 #include "clang/AST/CXXInheritance.h"
22 #include "clang/AST/StmtVisitor.h"
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.
31 class StringViewDangle
: public loplugin::FilteringPlugin
<StringViewDangle
>
34 explicit StringViewDangle(loplugin::InstantiationData
const& data
)
35 : FilteringPlugin(data
)
39 bool preRun() override
{ return true; }
41 virtual void run() override
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();
66 bool StringViewDangle::VisitCXXOperatorCallExpr(CXXOperatorCallExpr
const* cxxOperatorCallExpr
)
68 if (ignoreLocation(cxxOperatorCallExpr
))
71 auto op
= cxxOperatorCallExpr
->getOperator();
74 if (!loplugin::TypeCheck(cxxOperatorCallExpr
->getType())
75 .ClassOrStruct("basic_string_view")
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())
83 if (!isa
<MaterializeTemporaryExpr
>(expr
))
85 report(DiagnosticsEngine::Warning
, "view pointing into temporary i.e. dangling",
86 cxxOperatorCallExpr
->getExprLoc())
87 << cxxOperatorCallExpr
->getSourceRange();
91 bool StringViewDangle::VisitVarDecl(VarDecl
const* varDecl
)
93 if (ignoreLocation(varDecl
))
95 if (!loplugin::TypeCheck(varDecl
->getType()).ClassOrStruct("basic_string_view").StdNamespace())
97 if (!varDecl
->hasInit())
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())
104 if (!isa
<MaterializeTemporaryExpr
>(expr
))
106 report(DiagnosticsEngine::Warning
, "view pointing into temporary i.e. dangling",
107 varDecl
->getLocation())
108 << varDecl
->getSourceRange();
112 loplugin::Plugin::Registration
<StringViewDangle
> stringviewdangle("stringviewdangle");
115 #endif // LO_CLANG_SHARED_PLUGINS
117 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */