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
17 #include "clang/AST/Attr.h"
23 class OverrideVirtual
:
24 public loplugin::FilteringRewritePlugin
<OverrideVirtual
>
27 explicit OverrideVirtual(loplugin::InstantiationData
const & data
):
28 FilteringRewritePlugin(data
) {}
30 virtual bool preRun() override
;
31 virtual void run() override
;
33 bool VisitCXXMethodDecl(CXXMethodDecl
const * decl
);
36 std::set
<SourceLocation
> insertions_
;
39 bool OverrideVirtual::preRun() {
40 return compiler
.getLangOpts().CPlusPlus
41 && compiler
.getPreprocessor().getIdentifierInfo(
42 "LIBO_INTERNAL_ONLY")->hasMacroDefinition();
45 void OverrideVirtual::run() {
47 TraverseDecl(compiler
.getASTContext().getTranslationUnitDecl());
49 bool OverrideVirtual::VisitCXXMethodDecl(CXXMethodDecl
const * decl
) {
50 // As a heuristic, ignore declarations where the name is spelled out in an
51 // ignored location; that e.g. handles uses of the Q_OBJECT macro from
52 // external QtCore/qobjectdefs.h:
53 if (ignoreLocation(decl
) || !decl
->isFirstDecl()
54 || decl
->begin_overridden_methods() == decl
->end_overridden_methods()
55 || decl
->hasAttr
<OverrideAttr
>()
57 compiler
.getSourceManager().getSpellingLoc(
58 decl
->getNameInfo().getLoc())))
63 isInUnoIncludeFile(decl
->getSourceRange().getBegin())
64 ? "SAL_OVERRIDE" : "override");
65 if (rewriter
!= nullptr) {
66 // In void MACRO(...); getSourceRange().getEnd() would (erroneously?)
67 // point at "MACRO" rather than ")", so make the loop always terminate
68 // at the first ";" or "{" instead of getSourceRange().getEnd():
70 bool seenSpace
= false;
71 //TODO: Whether to add a space after an inserted "SAL_OVERRIDE" should
72 // depend on the following token at the spelling location where
73 // "SAL_OVERRIDE" is inserted, not on the following token in the fully-
74 // macro-expanded view:
75 bool addSpace
= bool();
77 for (SourceLocation
l(decl
->getSourceRange().getBegin());;) {
78 SourceLocation
sl(compiler
.getSourceManager().getSpellingLoc(l
));
79 unsigned n
= Lexer::MeasureTokenLength(
80 sl
, compiler
.getSourceManager(), compiler
.getLangOpts());
81 StringRef
s(compiler
.getSourceManager().getCharacterData(sl
), n
);
82 //TODO: Looks like a Clang bug that in some cases like
83 // (filter/source/svg/svgexport.cxx)
85 // | #define TEXT_FIELD_GET_CLASS_NAME_METHOD( class_name ) \ |
86 // | virtual OUString getClassName() const \ |
88 // | static const char className[] = #class_name; \ |
89 // | return OUString( className ); \ |
92 // | TEXT_FIELD_GET_CLASS_NAME_METHOD( TextField ) |
94 // where "\<NL>" is followed directly by a real token without
95 // intervening whitespace, tokens "\<NL>virtual" and "\<NL>{" are
97 if (s
.startswith("\\\n")) {
101 if (s
== "=" || s
== "{") {
112 assert(parens
< std::numeric_limits
<unsigned>::max());
114 } else if (s
== ")") {
123 } else if (s
.startswith("/*") || s
.startswith("//") || s
== "\\") {
134 && compiler
.getSourceManager().isAtEndOfImmediateMacroExpansion(
137 n
= Lexer::MeasureTokenLength(
138 compiler
.getSourceManager().getSpellingLoc(l
),
139 compiler
.getSourceManager(), compiler
.getLangOpts());
141 l
= l
.getLocWithOffset(std::max
<unsigned>(n
, 1));
143 assert(loc
.isValid());
144 if (!insertions_
.insert(loc
).second
145 || insertTextAfterToken(
147 std::string(" ") + over
+ std::string(addSpace
? " " : "")))
153 DiagnosticsEngine::Warning
,
154 ("overriding virtual function declaration not marked '%0'"),
156 << over
<< decl
->getSourceRange();
157 for (auto i
= decl
->begin_overridden_methods();
158 i
!= decl
->end_overridden_methods(); ++i
)
161 DiagnosticsEngine::Note
, "overridden declaration is here",
163 << (*i
)->getSourceRange();
168 loplugin::Plugin::Registration
<OverrideVirtual
> overridevirtual("overridevirtual");
172 #endif // LO_CLANG_SHARED_PLUGINS
174 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */