diff options
Diffstat (limited to 'compilerplugins/clang')
-rw-r--r-- | compilerplugins/clang/compat.hxx | 10 | ||||
-rw-r--r-- | compilerplugins/clang/includeform.cxx | 94 |
2 files changed, 104 insertions, 0 deletions
diff --git a/compilerplugins/clang/compat.hxx b/compilerplugins/clang/compat.hxx index 990f0ac78c26..532ce462887b 100644 --- a/compilerplugins/clang/compat.hxx +++ b/compilerplugins/clang/compat.hxx @@ -10,6 +10,7 @@ #ifndef INCLUDED_COMPILERPLUGINS_CLANG_COMPAT_HXX #define INCLUDED_COMPILERPLUGINS_CLANG_COMPAT_HXX +#include <cstddef> #include <memory> #include <string> @@ -36,6 +37,15 @@ // Compatibility wrapper to abstract over (trivial) changes in the Clang API: namespace compat { +inline llvm::StringRef take_front(llvm::StringRef ref, std::size_t N = 1) { +#if CLANG_VERSION >= 40000 + return ref.take_front(N); +#else + auto const size = ref.size(); + return N >= size ? ref : ref.drop_back(size - N); +#endif +} + inline bool isLookupContext(clang::DeclContext const & ctxt) { #if CLANG_VERSION >= 30700 return ctxt.isLookupContext(); diff --git a/compilerplugins/clang/includeform.cxx b/compilerplugins/clang/includeform.cxx new file mode 100644 index 000000000000..b3ab195fbe09 --- /dev/null +++ b/compilerplugins/clang/includeform.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "compat.hxx" +#include "plugin.hxx" + +namespace { + +class IncludeForm final: public PPCallbacks, public loplugin::RewritePlugin { +public: + explicit IncludeForm(InstantiationData const & data): RewritePlugin(data) + { compat::addPPCallbacks(compiler.getPreprocessor(), this); } + +private: + void run() override {} + + void InclusionDirective( + SourceLocation HashLoc, Token const & IncludeTok, StringRef, + bool IsAngled, CharSourceRange FilenameRange, FileEntry const * File, + StringRef SearchPath, StringRef, clang::Module const *) override + { + if (ignoreLocation(HashLoc)) { + return; + } + if (File == nullptr) { // in case of "fatal error: '...' file not found" + return; + } + if (IncludeTok.getIdentifierInfo()->getPPKeywordID() != tok::pp_include) + { + return; + } + auto const uno = isInUnoIncludeFile(HashLoc) + && !compiler.getSourceManager().isInMainFile(HashLoc); + // exclude the various compat.cxx that are included in + // isInUnoIncludeFile + //TODO: 'uno' should be false if HashLoc is inside an + // '#ifdef LIBO_INTERNAL_ONLY' block + bool shouldUseAngles; + if (uno) { + shouldUseAngles + = (!(loplugin::hasPathnamePrefix(SearchPath, SRCDIR) + || loplugin::hasPathnamePrefix(SearchPath, BUILDDIR)) + || loplugin::hasPathnamePrefix( + SearchPath, WORKDIR "/UnpackedTarball")); + } else { + auto const file = StringRef( + compiler.getSourceManager().getPresumedLoc(HashLoc) + .getFilename()); + auto const dir = compat::take_front(file, file.rfind('/')); + shouldUseAngles = !loplugin::isSamePathname(SearchPath, dir); + } + if (shouldUseAngles == IsAngled) { + return; + } + if (rewriter != nullptr) { + auto last = FilenameRange.getEnd().getLocWithOffset(-1); + if ((compiler.getSourceManager().getCharacterData( + FilenameRange.getBegin())[0] + == (IsAngled ? '<' : '"')) + && (compiler.getSourceManager().getCharacterData(last)[0] + == (IsAngled ? '>' : '"')) + && replaceText( + FilenameRange.getBegin(), 1, shouldUseAngles ? "<" : "\"") + && replaceText(last, 1, shouldUseAngles ? ">" : "\"")) + { + //TODO: atomically only replace both or neither + return; + } + } + report( + DiagnosticsEngine::Warning, + ("%select{|in UNO API include file, }0replace" + " %select{\"...\"|<...>}1 include form with" + " %select{\"...\"|<...>}2 for inclusion of %select{%select{a" + " source file next to the current source file|a source file not" + " next to the current source file, or a header}2|%select{a source" + " file|a header}2}0, %3"), + FilenameRange.getBegin()) + << uno << IsAngled << shouldUseAngles << File->getName() + << FilenameRange; + } +}; + +static loplugin::Plugin::Registration<IncludeForm> reg("includeform", true); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |