1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/.
16 class RedundantInline
:
17 public RecursiveASTVisitor
<RedundantInline
>, public loplugin::RewritePlugin
20 explicit RedundantInline(loplugin::InstantiationData
const & data
):
21 RewritePlugin(data
) {}
24 if (compiler
.getLangOpts().CPlusPlus
) {
25 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
29 bool VisitFunctionDecl(FunctionDecl
const * decl
) {
30 if (ignoreLocation(decl
) || !decl
->isInlineSpecified()
31 || !(decl
->doesThisDeclarationHaveABody()
32 || decl
->isExplicitlyDefaulted())
33 || !(decl
->getLexicalDeclContext()->isRecord()
34 || decl
->isConstexpr()))
38 auto l1
= unwindToQObject(decl
->getLocStart());
39 if (l1
.isValid() && l1
== unwindToQObject(decl
->getLocEnd())) {
42 SourceLocation inlineLoc
;
44 auto end
= Lexer::getLocForEndOfToken(
45 compiler
.getSourceManager().getExpansionLoc(decl
->getLocEnd()), 0,
46 compiler
.getSourceManager(), compiler
.getLangOpts());
47 assert(end
.isValid());
48 for (auto loc
= compiler
.getSourceManager().getExpansionLoc(
50 loc
!= end
; loc
= loc
.getLocWithOffset(std::max
<unsigned>(n
, 1)))
52 n
= Lexer::MeasureTokenLength(
53 loc
, compiler
.getSourceManager(), compiler
.getLangOpts());
54 StringRef
s(compiler
.getSourceManager().getCharacterData(loc
), n
);
55 //TODO: see compilerplugins/clang/override.cxx:
56 if (s
.startswith("\\\n")) {
60 if (!compiler
.getSourceManager().isMacroArgExpansion(loc
)) {
64 } else if (s
== "#") {
65 // Hard to pick the right 'inline' in code like
74 // so just give up once a preprocessing directive is seen:
78 if (rewriter
!= nullptr && inlineLoc
.isValid()) {
79 for (auto loc
= inlineLoc
.getLocWithOffset(
80 std::max
<unsigned>(n
, 1));;)
83 unsigned n2
= Lexer::MeasureTokenLength(
84 loc
, compiler
.getSourceManager(), compiler
.getLangOpts());
86 compiler
.getSourceManager().getCharacterData(loc
), n2
);
87 //TODO: see compilerplugins/clang/override.cxx:
88 if (s
.startswith("\\\n")) {
94 n2
= std::max
<unsigned>(n2
, 1);
96 loc
= loc
.getLocWithOffset(n2
);
98 if (removeText(inlineLoc
, n
, RewriteOptions(RemoveLineIfEmpty
))) {
103 DiagnosticsEngine::Warning
,
104 "function definition redundantly declared 'inline'",
105 inlineLoc
.isValid() ? inlineLoc
: decl
->getLocStart())
106 << decl
->getSourceRange();
111 SourceLocation
unwindToQObject(SourceLocation
const & loc
) {
112 if (!loc
.isMacroID()) {
113 return SourceLocation();
115 auto l
= compiler
.getSourceManager().getImmediateMacroCallerLoc(loc
);
117 (Lexer::getImmediateMacroName(
118 loc
, compiler
.getSourceManager(), compiler
.getLangOpts())
120 ? l
: unwindToQObject(l
);
124 loplugin::Plugin::Registration
<RedundantInline
> reg("redundantinline", true);
128 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */