[Libreoffice-commits] .: 4 commits - compilerplugins/clang compilerplugins/Makefile-clang.mk config/config_clang.h.in configure.ac
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Fri Jan 4 06:28:23 PST 2013
compilerplugins/Makefile-clang.mk | 1
compilerplugins/clang/lclstaticfix.cxx | 4
compilerplugins/clang/plugin.cxx | 110 +++++++++++++++++++---
compilerplugins/clang/plugin.hxx | 28 +++++
compilerplugins/clang/postfixincrementfix.cxx | 3
compilerplugins/clang/removeforwardstringdecl.cxx | 76 +++++++++++++++
compilerplugins/clang/removeforwardstringdecl.hxx | 34 ++++++
config/config_clang.h.in | 3
configure.ac | 3
9 files changed, 241 insertions(+), 21 deletions(-)
New commits:
commit d5ea81b87b8a19b23007691c8b14e6787ecb0290
Author: LuboÅ¡ LuÅák <l.lunak at suse.cz>
Date: Thu Jan 3 22:57:46 2013 +0100
handle case of SRCDIR == BUILDDIR
Change-Id: I9daea65dc28ab13776a7c4319e5d5811515fe160
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index 348386f..d6bc910 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -253,7 +253,7 @@ class PluginHandler
else if( strncmp( e->getName(), WORKDIR, strlen( WORKDIR )) == 0 )
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
"modified source in workdir/ : %0 [loplugin]" )) << e->getName();
- else if( strncmp( e->getName(), BUILDDIR, strlen( BUILDDIR )) == 0 )
+ else if( strcmp( SRCDIR, BUILDDIR ) != 0 && strncmp( e->getName(), BUILDDIR, strlen( BUILDDIR )) == 0 )
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
"modified source in build dir : %0 [loplugin]" )) << e->getName();
else if( strncmp( e->getName(), SRCDIR, strlen( SRCDIR )) == 0 )
commit 258aca9924d9e47737d750356d45227126dcf6a7
Author: LuboÅ¡ LuÅák <l.lunak at suse.cz>
Date: Thu Jan 3 20:23:51 2013 +0100
rewriter plugin for removing forward rtl string declarations
Change-Id: I12bf38985ae62756973c05aacf762ae3c405ac9b
diff --git a/compilerplugins/Makefile-clang.mk b/compilerplugins/Makefile-clang.mk
index 6031fe1..e652e44 100644
--- a/compilerplugins/Makefile-clang.mk
+++ b/compilerplugins/Makefile-clang.mk
@@ -14,6 +14,7 @@ CLANGSRC= \
bodynotinblock.cxx \
lclstaticfix.cxx \
postfixincrementfix.cxx \
+ removeforwardstringdecl.cxx \
sallogareas.cxx \
unusedvariablecheck.cxx \
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index 22bac0c..348386f 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -22,6 +22,7 @@
#include "bodynotinblock.hxx"
#include "lclstaticfix.hxx"
#include "postfixincrementfix.hxx"
+#include "removeforwardstringdecl.hxx"
#include "sallogareas.hxx"
#include "unusedvariablecheck.hxx"
@@ -192,6 +193,7 @@ class PluginHandler
, bodyNotInBlock( context )
, lclStaticFix( context, rewriter )
, postfixIncrementFix( context, rewriter )
+ , removeForwardStringDecl( context, rewriter )
, salLogAreas( context )
, unusedVariableCheck( context )
{
@@ -204,6 +206,8 @@ class PluginHandler
lclStaticFix.run();
else if( isArg( "postfixincrementfix" ))
postfixIncrementFix.run();
+ else if( isArg( "removeforwardstringdecl" ))
+ removeForwardStringDecl.run();
else if( args.empty())
{
bodyNotInBlock.run();
@@ -292,6 +296,7 @@ class PluginHandler
BodyNotInBlock bodyNotInBlock;
LclStaticFix lclStaticFix;
PostfixIncrementFix postfixIncrementFix;
+ RemoveForwardStringDecl removeForwardStringDecl;
SalLogAreas salLogAreas;
UnusedVariableCheck unusedVariableCheck;
};
diff --git a/compilerplugins/clang/removeforwardstringdecl.cxx b/compilerplugins/clang/removeforwardstringdecl.cxx
new file mode 100644
index 0000000..45891d5
--- /dev/null
+++ b/compilerplugins/clang/removeforwardstringdecl.cxx
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * Based on LLVM/Clang.
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ */
+
+#include "removeforwardstringdecl.hxx"
+
+#include <clang/AST/ASTContext.h>
+#include <clang/Basic/SourceManager.h>
+
+/*
+This is a rewriter.
+
+Remove all forward declarations of rtl strings. I.e. 'namespace rtl { class OUString; }' etc.
+*/
+
+namespace loplugin
+{
+
+RemoveForwardStringDecl::RemoveForwardStringDecl( ASTContext& context, Rewriter& rewriter )
+ : RewritePlugin( context, rewriter )
+ {
+ }
+
+void RemoveForwardStringDecl::run()
+ {
+ TraverseDecl( context.getTranslationUnitDecl());
+ }
+
+bool RemoveForwardStringDecl::VisitNamespaceDecl( NamespaceDecl* declaration )
+ {
+ if( ignoreLocation( declaration ))
+ return true;
+ if( declaration->getQualifiedNameAsString() != "rtl" )
+ return true;
+ bool canRemove = true;
+ for( NamespaceDecl::decl_iterator it = declaration->decls_begin();
+ it != declaration->decls_end();
+ ++it )
+ {
+ if( *it != NULL )
+ {
+ if( !tryRemoveStringForwardDecl( *it ))
+ canRemove = false;
+ }
+ }
+ if( canRemove ) // contained only forward decls that we removed
+ removeText( declaration->getSourceRange(), RemoveLineIfEmpty );
+ return true;
+ }
+
+bool RemoveForwardStringDecl::tryRemoveStringForwardDecl( const Decl* decl )
+ {
+ const CXXRecordDecl* classdecl = dyn_cast< CXXRecordDecl >( decl );
+ if( classdecl == NULL )
+ return false;
+ if( !classdecl->isFreeStanding() || classdecl->isCompleteDefinition())
+ return false; // not a simple forward declaration
+ if( classdecl->getName() == "OString" || classdecl->getName() == "OUString"
+ || classdecl->getName() == "OStringBuffer" || classdecl->getName() == "OUStringBuffer"
+ || classdecl->getName() == "OStringHash" || classdecl->getName() == "OUStringHash"
+ || classdecl->getName() == "OStringLiteral" || classdecl->getName() == "OUStringLiteral" )
+ {
+ removeText( SourceRange( classdecl->getOuterLocStart(), classdecl->getLocEnd()),
+ RemoveLineIfEmpty | RemoveWholeStatement );
+ return true;
+ }
+ return false;
+ }
+
+} // namespace
diff --git a/compilerplugins/clang/removeforwardstringdecl.hxx b/compilerplugins/clang/removeforwardstringdecl.hxx
new file mode 100644
index 0000000..7f40e37
--- /dev/null
+++ b/compilerplugins/clang/removeforwardstringdecl.hxx
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * Based on LLVM/Clang.
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+ */
+
+#ifndef REMOVEFORWARDSTRINGDECL_H
+#define REMOVEFORWARDSTRINGDECL_H
+
+#include "plugin.hxx"
+
+namespace loplugin
+{
+
+class RemoveForwardStringDecl
+ : public RecursiveASTVisitor< RemoveForwardStringDecl >
+ , public RewritePlugin
+ {
+ public:
+ explicit RemoveForwardStringDecl( ASTContext& context, Rewriter& rewriter );
+ void run();
+ bool VisitNamespaceDecl( NamespaceDecl* declaration );
+ private:
+ bool tryRemoveStringForwardDecl( const Decl* decl );
+ };
+
+} // namespace
+
+#endif // REMOVEFORWARDSTRINGDECL_H
+
commit c26e655264f03bb8bc484130ab2f539a9f831f16
Author: LuboÅ¡ LuÅák <l.lunak at suse.cz>
Date: Thu Dec 20 23:08:52 2012 +0100
support for removing a statement as a whole
Change-Id: Icb7b017a0c76a6169f0f629bb40bf97449c75837
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index 6535e1a..22bac0c 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -105,22 +105,47 @@ bool RewritePlugin::insertTextBefore( SourceLocation Loc, StringRef Str )
bool RewritePlugin::removeText( SourceLocation Start, unsigned Length, RewriteOptions opts )
{
- if( rewriter.RemoveText( Start, Length, opts ))
- return reportEditFailure( Start );
- return true;
+ return removeText( SourceRange( Start, Start.getLocWithOffset( Length )), opts );
}
-bool RewritePlugin::removeText( CharSourceRange range, RewriteOptions opts )
+bool RewritePlugin::removeText( SourceRange range, RewriteOptions opts )
{
+ if( opts.RemoveWholeStatement )
+ {
+ if( !adjustForWholeStatement( &range ))
+ return reportEditFailure( range.getBegin());
+ }
if( rewriter.RemoveText( range, opts ))
return reportEditFailure( range.getBegin());
return true;
}
-bool RewritePlugin::removeText( SourceRange range, RewriteOptions opts )
+bool RewritePlugin::adjustForWholeStatement( SourceRange* range )
{
- if( rewriter.RemoveText( range, opts ))
- return reportEditFailure( range.getBegin());
+ SourceManager& SM = rewriter.getSourceMgr();
+ SourceLocation fileStartLoc = SM.getLocForStartOfFile( SM.getFileID( range->getBegin()));
+ if( fileStartLoc.isInvalid())
+ return false;
+ bool invalid = false;
+ const char* fileBuf = SM.getCharacterData( fileStartLoc, &invalid );
+ if( invalid )
+ return false;
+ const char* startBuf = SM.getCharacterData( range->getBegin(), &invalid );
+ if( invalid )
+ return false;
+ const char* endBuf = SM.getCharacterData( range->getEnd(), &invalid );
+ if( invalid )
+ return false;
+ const char* startSpacePos = startBuf;
+ // do not skip \n here, RemoveLineIfEmpty can take care of that
+ --startSpacePos;
+ while( startSpacePos >= fileBuf && ( *startSpacePos == ' ' || *startSpacePos == '\t' ))
+ --startSpacePos;
+ const char* semiPos = strchr( endBuf, ';' );
+ if( semiPos == NULL )
+ return false;
+ *range = SourceRange( range->getBegin().getLocWithOffset( startSpacePos - startBuf + 1 ),
+ range->getEnd().getLocWithOffset( semiPos - endBuf + 1 ));
return true;
}
diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx
index 2a587ad..b9409b2 100644
--- a/compilerplugins/clang/plugin.hxx
+++ b/compilerplugins/clang/plugin.hxx
@@ -44,18 +44,39 @@ class RewritePlugin
public:
explicit RewritePlugin( ASTContext& context, Rewriter& rewriter );
protected:
- typedef Rewriter::RewriteOptions RewriteOptions;
+ // This enum allows passing just 'RemoveLineIfEmpty' to functions below.
+ enum RemoveLineIfEmpty_t { RemoveLineIfEmpty };
+ // Use this to remove the declaration/statement as a whole, i.e. all whitespace before the statement
+ // and the trailing semicolor (is not part of the AST element range itself).
+ // The trailing semicolon must be present.
+ enum RemoveWholeStatement_t { RemoveWholeStatement };
+ enum RemoveLineIfEmptyAndWholeStatement_t { RemoveLineIfEmptyAndWholeStatement };
+ // syntactic sugar to be able to write 'RemoveLineIfEmpty | RemoveWholeStatement'
+ friend RemoveLineIfEmptyAndWholeStatement_t operator|( RemoveLineIfEmpty_t, RemoveWholeStatement_t )
+ { return RemoveLineIfEmptyAndWholeStatement; }
+ struct RewriteOptions
+ : public Rewriter::RewriteOptions
+ {
+ RewriteOptions() : RemoveWholeStatement( false ) {} // default
+ RewriteOptions( RemoveLineIfEmpty_t ) : RemoveWholeStatement( false ) { RemoveLineIfEmpty = true; }
+ RewriteOptions( RemoveWholeStatement_t ) : RemoveWholeStatement( true ) {}
+ RewriteOptions( RemoveLineIfEmptyAndWholeStatement_t ) : RemoveWholeStatement( true ) { RemoveLineIfEmpty = true; }
+ bool RemoveWholeStatement;
+ };
// These following insert/remove/replaceText functions map to functions
- // in clang::Rewriter, with two differences:
+ // in clang::Rewriter, with these differences:
// - they (more intuitively) return false on failure rather than true
// - they report a warning when the change cannot be done
+ // - There is RemoveWholeStatement to also remove the trailing semicolon when removing (must be there)
+ // and al preceding whitespace.
bool insertText( SourceLocation Loc, StringRef Str,
bool InsertAfter = true, bool indentNewLines = false );
bool insertTextAfter( SourceLocation Loc, StringRef Str );
bool insertTextAfterToken( SourceLocation Loc, StringRef Str );
bool insertTextBefore( SourceLocation Loc, StringRef Str );
bool removeText( SourceLocation Start, unsigned Length, RewriteOptions opts = RewriteOptions());
- bool removeText( CharSourceRange range, RewriteOptions opts = RewriteOptions());
+ // CharSourceRange not supported, unless really needed, as it makes RemoveSemicolon more complicated
+ //bool removeText( CharSourceRange range, RewriteOptions opts = RewriteOptions());
bool removeText( SourceRange range, RewriteOptions opts = RewriteOptions());
bool replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr );
bool replaceText( SourceRange range, StringRef NewStr );
@@ -63,6 +84,7 @@ class RewritePlugin
Rewriter& rewriter;
private:
bool reportEditFailure( SourceLocation loc );
+ bool adjustForWholeStatement( SourceRange* range );
};
inline
commit 217e3f2ea1e8983328364607f244daceeafca167
Author: LuboÅ¡ LuÅák <l.lunak at suse.cz>
Date: Thu Jan 3 20:15:21 2013 +0100
better handling of which files are processed by clang plugins
Check that only LO's files are processed, as there's no point otherwise.
Also warn about files in workdir/solver/builddir, as those are either
generated or copies. Try to automatically match include files from
solver to srcdir though, as that's where include files are usually
included from :(.
Change-Id: Ie8389e903f623a9d0e75015091acc0da78e76c3a
diff --git a/compilerplugins/clang/lclstaticfix.cxx b/compilerplugins/clang/lclstaticfix.cxx
index 9227af8..a5c765b 100644
--- a/compilerplugins/clang/lclstaticfix.cxx
+++ b/compilerplugins/clang/lclstaticfix.cxx
@@ -34,9 +34,7 @@ void LclStaticFix::run()
bool LclStaticFix::VisitFunctionDecl( FunctionDecl* declaration )
{
- // TODO also LO header files? or a subdir?
- // Only the .cxx file can be normally edited ... ?
- if( !context.getSourceManager().isFromMainFile( declaration->getLocStart()))
+ if( ignoreLocation( declaration ))
return true;
if( declaration->isCXXClassMember())
return true;
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index 62412e6..6535e1a 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -25,6 +25,8 @@
#include "sallogareas.hxx"
#include "unusedvariablecheck.hxx"
+#include <config_clang.h>
+
namespace loplugin
{
@@ -51,7 +53,19 @@ DiagnosticBuilder Plugin::report( DiagnosticsEngine::Level level, StringRef mess
bool Plugin::ignoreLocation( SourceLocation loc )
{
- return context.getSourceManager().isInSystemHeader( context.getSourceManager().getExpansionLoc( loc ));
+ SourceLocation expansionLoc = context.getSourceManager().getExpansionLoc( loc );
+ if( context.getSourceManager().isInSystemHeader( expansionLoc ))
+ return true;
+ bool invalid;
+ const char* bufferName = context.getSourceManager().getBufferName( expansionLoc, &invalid );
+ if( invalid )
+ return true;
+ if( strncmp( bufferName, OUTDIR, strlen( OUTDIR )) == 0
+ || strncmp( bufferName, WORKDIR, strlen( WORKDIR )) == 0
+ || strncmp( bufferName, BUILDDIR, strlen( BUILDDIR )) == 0
+ || strncmp( bufferName, SRCDIR, strlen( SRCDIR )) == 0 )
+ return false; // ok
+ return true;
}
@@ -182,24 +196,64 @@ class PluginHandler
++it )
{
const FileEntry* e = context.getSourceManager().getFileEntryForID( it->first );
- char* filename = new char[ strlen( e->getName()) + 100 ];
- sprintf( filename, "%s.new.%d", e->getName(), getpid());
+ DiagnosticsEngine& diag = context.getDiagnostics();
+ /* Check where the file actually is, and warn about cases where modification
+ most probably doesn't matter (generated files in workdir).
+ The order here is important, as OUTDIR and WORKDIR are often in SRCDIR/BUILDDIR,
+ and BUILDDIR is sometimes in SRCDIR. */
+ string modifyFile;
+ if( strncmp( e->getName(), OUTDIR, strlen( OUTDIR )) == 0 )
+ {
+ /* Try to find a matching file for a file in solver/ (include files
+ are usually included from there rather than from the source dir) if possible. */
+ if( strncmp( e->getName(), OUTDIR "/inc/", strlen( OUTDIR ) + strlen( "/inc/" )) == 0 )
+ {
+ string filename( e->getName());
+ int modulePos = strlen( OUTDIR ) + strlen( "/inc/" );
+ int moduleEnd = filename.find( '/', modulePos );
+ if( moduleEnd != string::npos )
+ {
+ modifyFile = SRCDIR "/" + filename.substr( modulePos, moduleEnd - modulePos )
+ + "/inc/" + filename.substr( modulePos );
+ }
+ }
+ if( modifyFile.empty())
+ diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
+ "modified source in solver/ : %0 [loplugin]" )) << e->getName();
+ }
+ else if( strncmp( e->getName(), WORKDIR, strlen( WORKDIR )) == 0 )
+ diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
+ "modified source in workdir/ : %0 [loplugin]" )) << e->getName();
+ else if( strncmp( e->getName(), BUILDDIR, strlen( BUILDDIR )) == 0 )
+ diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
+ "modified source in build dir : %0 [loplugin]" )) << e->getName();
+ else if( strncmp( e->getName(), SRCDIR, strlen( SRCDIR )) == 0 )
+ ; // ok
+ else
+ {
+ diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
+ "modified source in unknown location, not modifying : %0 [loplugin]" )) << e->getName();
+ continue; // --->
+ }
+ if( modifyFile.empty())
+ modifyFile = e->getName();
+ char* filename = new char[ modifyFile.length() + 100 ];
+ sprintf( filename, "%s.new.%d", modifyFile.c_str(), getpid());
string error;
bool ok = false;
raw_fd_ostream ostream( filename, error );
- DiagnosticsEngine& diag = context.getDiagnostics();
if( error.empty())
{
it->second.write( ostream );
ostream.close();
- if( !ostream.has_error() && rename( filename, e->getName()) == 0 )
+ if( !ostream.has_error() && rename( filename, modifyFile.c_str()) == 0 )
ok = true;
}
ostream.clear_error();
unlink( filename );
if( !ok )
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Error,
- "cannot write modified source to %0 (%1) [loplugin]" )) << e->getName() << error;
+ "cannot write modified source to %0 (%1) [loplugin]" )) << modifyFile << error;
delete[] filename;
}
}
diff --git a/compilerplugins/clang/postfixincrementfix.cxx b/compilerplugins/clang/postfixincrementfix.cxx
index c5c17fb..bfaf77c 100644
--- a/compilerplugins/clang/postfixincrementfix.cxx
+++ b/compilerplugins/clang/postfixincrementfix.cxx
@@ -28,8 +28,7 @@ void PostfixIncrementFix::run()
bool PostfixIncrementFix::VisitFunctionDecl( FunctionDecl* declaration )
{
- // TODO also LO header files? or a subdir?
- if( !context.getSourceManager().isFromMainFile( declaration->getLocStart()))
+ if( ignoreLocation( declaration ))
return true;
if( !declaration->doesThisDeclarationHaveABody())
return true;
diff --git a/config/config_clang.h.in b/config/config_clang.h.in
index 60ff5bf..9d87e7a 100644
--- a/config/config_clang.h.in
+++ b/config/config_clang.h.in
@@ -7,6 +7,9 @@ Settings related to Clang compiler plugins.
#ifndef CONFIG_CLANG_H
#define CONFIG_CLANG_H
+#undef BUILDDIR
+#undef OUTDIR
#undef SRCDIR
+#undef WORKDIR
#endif
diff --git a/configure.ac b/configure.ac
index 9f9527d67..bd5b074 100644
--- a/configure.ac
+++ b/configure.ac
@@ -107,6 +107,7 @@ AC_SUBST(BUILDDIR)
AC_SUBST(EXEEXT_FOR_BUILD)
AC_SUBST(x_Cygwin)
AC_DEFINE_UNQUOTED(SRCDIR,"$SRC_ROOT")
+AC_DEFINE_UNQUOTED(BUILDDIR,"$BUILDDIR")
if test "z$EUID" = "z0" -a "`uname -o 2>/dev/null`" = "Cygwin"; then
AC_MSG_ERROR([You must build LibreOffice as a normal user - not using an administrative account])
@@ -4092,6 +4093,8 @@ AC_SUBST(P_SEP)
AC_SUBST(SOLARVER)
AC_SUBST(WORKDIR)
AC_SUBST(PLATFORMID)
+AC_DEFINE_UNQUOTED(OUTDIR,"$OUTDIR")
+AC_DEFINE_UNQUOTED(WORKDIR,"$WORKDIR")
dnl ===================================================================
dnl Test which package format to use
More information about the Libreoffice-commits
mailing list