bump product version to 6.4.0.3
[LibreOffice.git] / compilerplugins / clang / plugin.hxx
blobebadc645ef7a250592755d4645b69666bfbb3f3f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * Based on LLVM/Clang.
7 * This file is distributed under the University of Illinois Open Source
8 * License. See LICENSE.TXT for details.
12 #ifndef PLUGIN_H
13 #define PLUGIN_H
15 #include <clang/AST/ASTContext.h>
16 #include <clang/AST/RecursiveASTVisitor.h>
17 #include <clang/Basic/FileManager.h>
18 #include <clang/Basic/SourceManager.h>
19 #include <clang/Frontend/CompilerInstance.h>
20 #include <clang/Lex/Preprocessor.h>
21 #include <unordered_map>
22 #include <vector>
24 #include <clang/Rewrite/Core/Rewriter.h>
26 #include "compat.hxx"
27 #include "pluginhandler.hxx"
29 using namespace clang;
30 using namespace llvm;
32 namespace loplugin
35 struct InstantiationData
37 const char* name;
38 PluginHandler& handler;
39 CompilerInstance& compiler;
40 Rewriter* rewriter;
43 /**
44 Base class for plugins.
46 If you want to create a non-rewriter action, inherit from this class. Remember to also
47 use Plugin::Registration.
49 class Plugin
51 public:
52 explicit Plugin( const InstantiationData& data );
53 virtual ~Plugin() {}
54 // The main function of the plugin.
55 // Note that for shared plugins, its functionality must be split into preRun() and postRun(),
56 // see sharedvisitor/generator.cxx .
57 virtual void run() = 0;
58 // Should be called from run() before TraverseDecl().
59 // If returns false, run() should not do anything.
60 virtual bool preRun() { return true; }
61 virtual void postRun() {}
62 template< typename T > class Registration;
63 // Returns location right after the end of the token that starts at the given location.
64 SourceLocation locationAfterToken( SourceLocation location );
65 virtual bool setSharedPlugin( Plugin* /*plugin*/, const char* /*name*/ ) { return false; }
66 enum { isPPCallback = false };
67 enum { isSharedPlugin = false };
68 protected:
69 DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation()) const;
70 bool ignoreLocation( SourceLocation loc ) const
71 { return handler.ignoreLocation(loc); }
72 bool ignoreLocation( const Decl* decl ) const;
73 bool ignoreLocation( const Stmt* stmt ) const;
74 CompilerInstance& compiler;
75 PluginHandler& handler;
76 /**
77 Returns the parent of the given AST node. Clang's internal AST representation doesn't provide this information,
78 it can only provide children, but getting the parent is often useful for inspecting a part of the AST.
80 const Stmt* getParentStmt( const Stmt* stmt );
81 Stmt* getParentStmt( Stmt* stmt );
82 const FunctionDecl* getParentFunctionDecl( const Stmt* stmt );
84 /**
85 Get filename of the given location. Use this instead of SourceManager::getFilename(), as that one
86 does not handle source with expanded #inline directives (used by Icecream for remote compilation).
88 StringRef getFilenameOfLocation(SourceLocation spellingLocation) const;
89 /**
90 Checks if the location is inside a UNO file, more specifically, if it forms part of the URE stable interface,
91 which is not allowed to be changed.
93 bool isInUnoIncludeFile(SourceLocation spellingLocation) const;
94 bool isInUnoIncludeFile(const FunctionDecl*) const;
96 bool isDebugMode() const { return handler.isDebugMode(); }
98 static bool isUnitTestMode();
100 bool containsPreprocessingConditionalInclusion(SourceRange range);
102 enum class IdenticalDefaultArgumentsResult { No, Yes, Maybe };
103 IdenticalDefaultArgumentsResult checkIdenticalDefaultArguments(
104 Expr const * argument1, Expr const * argument2);
106 private:
107 static void registerPlugin( Plugin* (*create)( const InstantiationData& ), const char* optionName,
108 bool isPPCallback, bool isSharedPlugin, bool byDefault );
109 template< typename T > static Plugin* createHelper( const InstantiationData& data );
110 bool evaluate(const Expr* expr, APSInt& x);
112 enum { isRewriter = false };
113 const char* name;
116 template<typename Derived>
117 class FilteringPlugin : public RecursiveASTVisitor<Derived>, public Plugin
119 public:
120 explicit FilteringPlugin( const InstantiationData& data ) : Plugin(data) {}
122 bool TraverseNamespaceDecl(NamespaceDecl * decl) {
123 if (ignoreLocation(compat::getBeginLoc(decl)))
124 return true;
125 return RecursiveASTVisitor<Derived>::TraverseNamespaceDecl(decl);
130 Base class for rewriter plugins.
132 Remember to also use Plugin::Registration.
134 class RewritePlugin
135 : public Plugin
137 public:
138 explicit RewritePlugin( const InstantiationData& data );
139 protected:
140 enum RewriteOption
142 // This enum allows passing just 'RemoveLineIfEmpty' to functions below.
143 // If the resulting line would be completely empty, it'll be removed.
144 RemoveLineIfEmpty = 1 << 0,
145 // Use this to remove the declaration/statement as a whole, i.e. all whitespace before the statement
146 // and the trailing semicolon (is not part of the AST element range itself).
147 // The trailing semicolon must be present.
148 RemoveWholeStatement = 1 << 1,
149 // Removes also all whitespace preceding and following the expression (completely, so that
150 // the preceding and following tokens would be right next to each other, follow with insertText( " " )
151 // if this is not wanted). Despite the name, indentation whitespace is not removed.
152 RemoveAllWhitespace = 1 << 2
154 struct RewriteOptions
155 : public Rewriter::RewriteOptions
157 RewriteOptions() : flags( 0 ) {}
158 explicit RewriteOptions( RewriteOption option );
159 const int flags;
161 // syntactic sugar to be able to write 'RemoveLineIfEmpty | RemoveWholeStatement'
162 friend RewriteOption operator|( RewriteOption option1, RewriteOption option2 );
163 // These following insert/remove/replaceText functions map to functions
164 // in clang::Rewriter, with these differences:
165 // - they (more intuitively) return false on failure rather than true
166 // - they report a warning when the change cannot be done
167 // - There are more options for easier removal of surroundings of a statement/expression.
168 bool insertText( SourceLocation Loc, StringRef Str,
169 bool InsertAfter = true, bool indentNewLines = false );
170 bool insertTextAfter( SourceLocation Loc, StringRef Str );
171 bool insertTextAfterToken( SourceLocation Loc, StringRef Str );
172 bool insertTextBefore( SourceLocation Loc, StringRef Str );
173 bool removeText( SourceLocation Start, unsigned Length, RewriteOptions opts = RewriteOptions());
174 bool removeText( CharSourceRange range, RewriteOptions opts = RewriteOptions());
175 bool removeText( SourceRange range, RewriteOptions opts = RewriteOptions());
176 bool replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr );
177 bool replaceText( SourceRange range, StringRef NewStr );
178 bool replaceText( SourceRange range, SourceRange replacementRange );
179 Rewriter* rewriter;
180 private:
181 template< typename T > friend class Plugin::Registration;
182 enum { isRewriter = true };
183 bool wouldRewriteWorkdir(SourceLocation loc);
184 bool reportEditFailure( SourceLocation loc );
185 bool adjustRangeForOptions( CharSourceRange* range, RewriteOptions options );
189 Plugin registration helper.
191 If you create a new helper class, create also an instance of this class to automatically register it.
192 The passed argument is name of the plugin, used for explicitly invoking rewriter plugins
193 (it is ignored for non-rewriter plugins).
195 @code
196 static Plugin::Registration< NameOfClass > X( "nameofclass" );
197 @endcode
199 template< typename T >
200 class Plugin::Registration
202 public:
203 Registration( const char* optionName, bool byDefault = !T::isRewriter );
206 class RegistrationCreate
208 public:
209 template< typename T, bool > static T* create( const InstantiationData& data );
212 inline
213 bool Plugin::ignoreLocation( const Decl* decl ) const
215 return ignoreLocation( decl->getLocation());
218 inline
219 bool Plugin::ignoreLocation( const Stmt* stmt ) const
221 // Invalid location can happen at least for ImplicitCastExpr of
222 // ImplicitParam 'self' in Objective C method declarations:
223 return compat::getBeginLoc(stmt).isValid() && ignoreLocation( compat::getBeginLoc(stmt));
226 template< typename T >
227 Plugin* Plugin::createHelper( const InstantiationData& data )
229 return new T( data );
232 template< typename T >
233 inline
234 Plugin::Registration< T >::Registration( const char* optionName, bool byDefault )
236 registerPlugin( &T::template createHelper< T >, optionName, T::isPPCallback, T::isSharedPlugin, byDefault );
239 inline
240 RewritePlugin::RewriteOptions::RewriteOptions( RewriteOption option )
241 : flags( option )
243 // Note that 'flags' stores also RemoveLineIfEmpty, it must be kept in sync with the base class.
244 if( flags & RewritePlugin::RemoveLineIfEmpty )
245 RemoveLineIfEmpty = true;
248 inline
249 RewritePlugin::RewriteOption operator|( RewritePlugin::RewriteOption option1, RewritePlugin::RewriteOption option2 )
251 return static_cast< RewritePlugin::RewriteOption >( int( option1 ) | int( option2 ));
254 template<typename Derived>
255 class FilteringRewritePlugin : public RecursiveASTVisitor<Derived>, public RewritePlugin
257 public:
258 explicit FilteringRewritePlugin( const InstantiationData& data ) : RewritePlugin(data) {}
260 bool TraverseNamespaceDecl(NamespaceDecl * decl) {
261 if (ignoreLocation(compat::getBeginLoc(decl)))
262 return true;
263 return RecursiveASTVisitor<Derived>::TraverseNamespaceDecl(decl);
267 void normalizeDotDotInFilePath(std::string&);
269 // Same as pathname.startswith(prefix), except on Windows, where pathname and
270 // prefix may also contain backslashes:
271 bool hasPathnamePrefix(StringRef pathname, StringRef prefix);
273 // Same as pathname == other, except on Windows, where pathname and other may
274 // also contain backslashes:
275 bool isSamePathname(StringRef pathname, StringRef other);
277 // It appears that, given a function declaration, there is no way to determine
278 // the language linkage of the function's type, only of the function's name
279 // (via FunctionDecl::isExternC); however, in a case like
281 // extern "C" { static void f(); }
283 // the function's name does not have C language linkage while the function's
284 // type does (as clarified in C++11 [decl.link]); cf. <http://clang-developers.
285 // 42468.n3.nabble.com/Language-linkage-of-function-type-tt4037248.html>
286 // "Language linkage of function type":
287 bool hasCLanguageLinkageType(FunctionDecl const * decl);
289 // Count the number of times the base class is present in the subclass hierarchy
291 int derivedFromCount(clang::QualType subclassType, clang::QualType baseclassType);
292 int derivedFromCount(const CXXRecordDecl* subtypeRecord, const CXXRecordDecl* baseRecord);
295 } // namespace
297 #endif // COMPILEPLUGIN_H
299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */