GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / compilerplugins / clang / rtlconstasciimacro.cxx
blob0d7cc05824e36fe215c39a0c1eb4f9bc920b96af
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.
13 This is a rewriter.
15 Remove uses of the macro RTL_CONSTASCII_USTRINGPARAM. One run is for one
16 specific use (see below), modify source to remove other uses.
19 #include "plugin.hxx"
21 #include <clang/Lex/Preprocessor.h>
23 namespace loplugin
26 class RtlConstAsciiMacro
27 : public RecursiveASTVisitor< RtlConstAsciiMacro >
28 , public PPCallbacks
29 , public RewritePlugin
31 public:
32 explicit RtlConstAsciiMacro( CompilerInstance& compiler, Rewriter& rewriter );
33 virtual void run() override;
34 bool VisitCXXConstructExpr( CXXConstructExpr* expr );
35 bool VisitCXXTemporaryObjectExpr( CXXTemporaryObjectExpr* expr );
36 bool VisitStringLiteral( const StringLiteral* literal );
37 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
38 virtual void MacroExpands( const Token& macro, const MacroInfo* info, SourceRange range ) override;
39 #else
40 virtual void MacroExpands( const Token& macro, const MacroDirective* directive,
41 SourceRange range, const MacroArgs* args ) override;
42 #endif
43 enum { isPPCallback = true };
44 private:
45 map< SourceLocation, SourceLocation > expansions; // start location -> end location
46 bool searchingForString;
47 bool suitableString;
50 RtlConstAsciiMacro::RtlConstAsciiMacro( CompilerInstance& compiler, Rewriter& rewriter )
51 : RewritePlugin( compiler, rewriter )
52 , searchingForString( false )
54 compiler.getPreprocessor().addPPCallbacks( this );
57 void RtlConstAsciiMacro::run()
59 TraverseDecl( compiler.getASTContext().getTranslationUnitDecl());
63 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
64 void RtlConstAsciiMacro::MacroExpands( const Token& macro, const MacroInfo*, SourceRange range )
65 #else
66 void RtlConstAsciiMacro::MacroExpands( const Token& macro, const MacroDirective*,
67 SourceRange range, const MacroArgs* )
68 #endif
70 if( macro.getIdentifierInfo()->getName() != "RTL_CONSTASCII_USTRINGPARAM" )
71 return;
72 expansions[ range.getBegin() ] = range.getEnd();
75 /* Remove use with the following ctor:
76 OUString( const sal_Char * value, sal_Int32 length,
77 rtl_TextEncoding encoding,
78 sal_uInt32 convertFlags = OSTRING_TO_OUSTRING_CVTFLAGS )
79 This means searching for CXXConstructExpr.
80 For removal when used with functions it should check e.g. for CallExpr.
82 bool RtlConstAsciiMacro::VisitCXXConstructExpr( CXXConstructExpr* expr )
84 if( ignoreLocation( expr ))
85 return true;
86 if( expr->getNumArgs() != 4 )
87 return true;
88 // The last argument should be the default one when the macro is used.
89 if( dyn_cast< CXXDefaultArgExpr >( expr->getArg( 3 )) == NULL )
90 return true;
91 if( expr->getConstructor()->getQualifiedNameAsString() != "rtl::OUString::OUString" )
92 return true;
93 const SourceManager& src = compiler.getSourceManager();
94 SourceLocation start = src.getExpansionLoc( expr->getArg( 0 )->getLocStart());
95 // Macro fills in the first 3 arguments, so they must all come from the same expansion.
96 if( start != src.getExpansionLoc( expr->getArg( 2 )->getLocEnd()))
97 return true;
98 if( expansions.find( start ) == expansions.end())
99 return true;
100 SourceLocation end = expansions[ start ];
101 // Remove the location, since sometimes the same code may be processed more than once
102 // (e.g. non-trivial default arguments).
103 expansions.erase( start );
104 // Check if the string argument to the macro is suitable.
105 searchingForString = true;
106 suitableString = false;
107 TraverseStmt( expr->getArg( 0 ));
108 searchingForString = false;
109 if( !suitableString )
110 return true;
111 // Seach for '(' (don't just remove a given length to handle possible whitespace).
112 const char* text = compiler.getSourceManager().getCharacterData( start );
113 const char* pos = text;
114 while( *pos != '(' )
115 ++pos;
116 ++pos;
117 if( text[ -1 ] == ' ' && *pos == ' ' )
118 ++pos; // do not leave two spaces
119 removeText( start, pos - text, RemoveLineIfEmpty );
120 const char* textend = compiler.getSourceManager().getCharacterData( end );
121 if( textend[ -1 ] == ' ' && textend[ 1 ] == ' ' )
122 removeText( end, 2, RemoveLineIfEmpty ); // Remove ') '.
123 else
124 removeText( end, 1, RemoveLineIfEmpty ); // Remove ')'.
125 return true;
128 bool RtlConstAsciiMacro::VisitCXXTemporaryObjectExpr( CXXTemporaryObjectExpr* expr )
130 return VisitCXXConstructExpr( expr );
133 bool RtlConstAsciiMacro::VisitStringLiteral( const StringLiteral* literal )
135 if( !searchingForString )
136 return true;
137 if( suitableString ) // two string literals?
139 report( DiagnosticsEngine::Warning, "cannot analyze RTL_CONSTASCII_USTRINGPARAM (plugin needs fixing)" )
140 << literal->getSourceRange();
141 return true;
143 if( !literal->isAscii()) // ignore
144 return true;
145 if( !literal->containsNonAsciiOrNull())
146 suitableString = true;
147 return true;
150 static Plugin::Registration< RtlConstAsciiMacro > X( "rtlconstasciimacro" );
152 } // namespace
154 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */