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/.
15 #include <sys/types.h>
23 This is intended to be run as the second stage of the "unnecessaryvirtuals" clang plugin.
29 public loplugin::FilteringRewritePlugin
<RemoveVirtuals
>
32 explicit RemoveVirtuals(InstantiationData
const & data
);
35 virtual void run() override
{ TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl()); }
37 bool VisitCXXMethodDecl( const CXXMethodDecl
* var
);
39 // I use a brute-force approach - mmap the results file and do a linear search on it
40 // It works surprisingly well, because the file is small enough to fit into L2 cache on modern CPU's
46 size_t getFilesize(const char* filename
)
53 RemoveVirtuals::RemoveVirtuals(InstantiationData
const & data
): FilteringRewritePlugin(data
)
55 static const char sInputFile
[] = SRCDIR
"/result.txt";
56 mmapFilesize
= getFilesize(sInputFile
);
58 mmapFD
= open(sInputFile
, O_RDONLY
, 0);
61 mmappedData
= static_cast<char*>(mmap(NULL
, mmapFilesize
, PROT_READ
, MAP_PRIVATE
| MAP_POPULATE
, mmapFD
, 0));
62 assert(mmappedData
!= NULL
);
65 RemoveVirtuals::~RemoveVirtuals()
68 int rc
= munmap(mmappedData
, mmapFilesize
);
73 std::string
niceName(const CXXMethodDecl
* functionDecl
)
76 functionDecl
->getParent()->getQualifiedNameAsString() + "::"
77 + functionDecl
->getReturnType().getAsString() + "-"
78 + functionDecl
->getNameAsString() + "(";
79 for (const ParmVarDecl
*pParmVarDecl
: functionDecl
->params()) {
80 s
+= pParmVarDecl
->getType().getAsString();
84 if (functionDecl
->isConst()) {
90 bool RemoveVirtuals::VisitCXXMethodDecl( const CXXMethodDecl
* functionDecl
)
92 if (rewriter
== nullptr) {
95 if (ignoreLocation(functionDecl
)) {
98 // ignore stuff that forms part of the stable URE interface
99 if (isInUnoIncludeFile(functionDecl
)) {
103 // don't mess with templates
104 if (functionDecl
->getParent()->getDescribedClassTemplate() != nullptr) {
107 if (functionDecl
->getTemplatedKind() != FunctionDecl::TK_NonTemplate
) {
111 if (!functionDecl
->isVirtualAsWritten()) {
114 std::string aNiceName
= "\n" + niceName(functionDecl
) + "\n";
115 const char *aNiceNameStr
= aNiceName
.c_str();
116 char* found
= std::search(mmappedData
, mmappedData
+ mmapFilesize
, aNiceNameStr
, aNiceNameStr
+ strlen(aNiceNameStr
));
117 if(!(found
< mmappedData
+ mmapFilesize
)) {
120 if (functionDecl
->isPure()) {
121 if (!removeText(functionDecl
->getSourceRange())) {
123 DiagnosticsEngine::Warning
,
124 "Could not remove unused pure virtual method",
125 functionDecl
->getLocStart())
126 << functionDecl
->getSourceRange();
129 std::string aOrigText
= rewriter
->getRewrittenText(functionDecl
->getSourceRange());
130 size_t iVirtualTokenIndex
= aOrigText
.find_first_of("virtual ");
131 if (iVirtualTokenIndex
== std::string::npos
) {
134 if (!replaceText(functionDecl
->getSourceRange(), aOrigText
.replace(iVirtualTokenIndex
, strlen("virtual "), ""))) {
136 DiagnosticsEngine::Warning
,
137 "Could not remove virtual qualifier from method",
138 functionDecl
->getLocStart())
139 << functionDecl
->getSourceRange();
146 loplugin::Plugin::Registration
< RemoveVirtuals
> X("removevirtuals", false);
150 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */