1 //  deprecated_name_check implementation  -----------------------------------//
2 
3 //  Copyright Beman Dawes   2002.
4 //  Copyright Gennaro Prota 2006.
5 //  Copyright Hartmut Kaiser 2016.
6 //
7 //  Distributed under the Boost Software License, Version 1.0.
8 //  (See accompanying file LICENSE_1_0.txt or copy at
9 //  http://www.boost.org/LICENSE_1_0.txt)
10 
11 #include <hpx/config/defines.hpp>
12 
13 #include <algorithm>
14 
15 #include "deprecated_name_check.hpp"
16 #include "boost/regex.hpp"
17 #include "boost/lexical_cast.hpp"
18 #include "function_hyper.hpp"
19 
20 #include <set>
21 #include <string>
22 #include <vector>
23 
24 namespace boost
25 {
26   namespace inspect
27   {
28     deprecated_names const names[] =
29     {
30       // boost::xyz
31       { "(\\bboost\\s*::\\s*move\\b)", "std::move" },
32       { "(\\bboost\\s*::\\s*forward\\b)", "std::forward" },
33       { "(\\bboost\\s*::\\s*noncopyable\\b)", "HPX_NON_COPYABLE" },
34       { "(\\bboost\\s*::\\s*result_of\\b)", "std::result_of" },
35       { "(\\bboost\\s*::\\s*decay\\b)", "std::decay" },
36       { "(\\bboost\\s*::\\s*enable_if\\b)", "std::enable_if" },
37       { "(\\bboost\\s*::\\s*disable_if\\b)", "std::enable_if" },
38       { "(\\bboost\\s*::\\s*enable_if_c\\b)", "std::enable_if" },
39       { "(\\bboost\\s*::\\s*disable_if_c\\b)", "std::enable_if" },
40       { "(\\bboost\\s*::\\s*lazy_enable_if\\b)", "hpx::util::lazy_enable_if" },
41       { "(\\bboost\\s*::\\s*lazy_disable_if\\b)", "hpx::util::lazy_enable_if" },
42       { "(\\bboost\\s*::\\s*lazy_enable_if_c\\b)", "hpx::util::lazy_enable_if" },
43       { "(\\bboost\\s*::\\s*lazy_disable_if_c\\b)", "hpx::util::lazy_enable_if" },
44       { "(\\bboost\\s*::\\s*mpl\\b)", "no specific replacement" },
45       { "(\\bboost\\s*::\\s*(is_[^\\s]*?\\b))", "std::\\2" },
46       { "(\\bboost\\s*::\\s*(add_[^\\s]*?\\b))", "std::\\2" },
47       { "(\\bboost\\s*::\\s*(remove_[^\\s]*?\\b))", "std::\\2" },
48       { "(\\bboost\\s*::\\s*(((false)|(true))_type\\b))", "std::\\2" },
49       { "(\\bboost\\s*::\\s*lock_guard\\b)", "std::lock_guard" },
50       { "(\\bboost\\s*::\\s*unordered_map\\b)", "std::unordered_map" },
51       { "(\\bboost\\s*::\\s*unordered_multimap\\b)", "std::unordered_multimap" },
52       { "(\\bboost\\s*::\\s*unordered_set\\b)", "std::unordered_set" },
53       { "(\\bboost\\s*::\\s*unordered_multiset\\b)", "std::unordered_multiset" },
54       { "(\\bboost\\s*::\\s*detail\\s*::\\s*atomic_count\\b)",
55         "hpx::util::atomic_count" },
56       { "(\\bboost\\s*::\\s*function\\b)", "hpx::util::function_nonser" },
57       { "(\\bboost\\s*::\\s*shared_ptr\\b)", "std::shared_ptr" },
58       { "(\\bboost\\s*::\\s*make_shared\\b)", "std::make_shared" },
59       { "(\\bboost\\s*::\\s*enable_shared_from_this\\b)",
60         "std::enable_shared_from_this" },
61       { "(\\bboost\\s*::\\s*bind\\b)", "hpx::util::bind" },
62       { "(\\bboost\\s*::\\s*unique_lock\\b)", "std::unique_lock" },
63       { "(\\bboost\\s*::\\s*chrono\\b)", "std::chrono" },
64       { "(\\bboost\\s*::\\s*reference_wrapper\\b)", "std::reference_wrapper" },
65       { "(\\bboost\\s*::\\s*(c?ref)\\b)", "std::\\2" },
66       { "(\\bboost\\s*::\\s*(u?int[0-9]+_t)\\b)", "std::\\2" },
67       { "(\\bboost\\s*::\\s*thread\\b)", "hpx::compat::thread" },
68       { "(\\bboost\\s*::\\s*this_thread::\\s*get_id\\b)", "hpx::compat::this_thread::get_id" },
69       { "(\\bboost\\s*::\\s*this_thread::\\s*yield\\b)", "hpx::compat::this_thread::yield" },
70       { "(\\bboost\\s*::\\s*this_thread::\\s*sleep_until\\b)", "hpx::compat::this_thread::sleep_until" },
71       { "(\\bboost\\s*::\\s*this_thread::\\s*sleep_for\\b)", "hpx::compat::this_thread::sleep_for" },
72       { "(\\bboost\\s*::\\s*mutex\\b)", "hpx::compat::mutex" },
73       { "(\\bboost\\s*::\\s*recursive_mutex\\b)", "hpx::compat::recursive_mutex" },
74       { "(\\bboost\\s*::\\s*once_flag\\b)", "hpx::compat::once_flag" },
75       { "(\\bboost\\s*::\\s*call_once\\b)", "hpx::compat::call_once" },
76       { "(\\bboost\\s*::\\s*cv_status\\b)", "hpx::compat::cv_status" },
77       { "(\\bboost\\s*::\\s*condition_variable\\b)", "hpx::compat::condition_variable" },
78       { "(\\bboost\\s*::\\s*barrier\\b)", "hpx::compat::barrier" },
79       { "(\\bboost\\s*::\\s*exception_ptr\\b)", "std::exception_ptr" },
80       { "(\\bboost\\s*::\\s*copy_exception\\b)", "std::make_exception_ptr" },
81       { "(\\bboost\\s*::\\s*current_exception\\b)", "std::current_exception" },
82       { "(\\bboost\\s*::\\s*rethrow_exception\\b)", "std::rethrow_exception" },
83       { "(\\bboost\\s*::\\s*enable_error_info\\b)", "hpx::throw_with_info" },
84       { "(\\bboost\\s*::\\s*iterator_range\\b)", "hpx::util::iterator_range" },
85       { "(\\bboost\\s*::\\s*make_iterator_range\\b)", "hpx::util::make_iterator_range" },
86       { "(\\bboost\\s*::\\s*atomic_flag\\b)", "std::atomic_flag" },
87       { "(\\bboost\\s*::\\s*atomic\\b)", "std::atomic" },
88       { "(\\bboost\\s*::\\s*memory_order_((relaxed)|(acquire)|(release)|"
89         "(acq_rel)|(seq_cst))\\b)", "std::memory_order_\\2" },
90       { "(\\bboost\\s*::\\s*random\\s*::\\s*([^\\s]*)\\b)", "std::\\2" },
91       { "(\\bboost\\s*::\\s*format\\b)", "hpx::util::format[_to]" },
92       /////////////////////////////////////////////////////////////////////////
93       { "((\\bhpx::\\b)?\\btraits\\s*::\\bis_callable\\b)", "\\2traits::is_invocable[_r]" },
94       { "((\\bhpx::\\b)?\\butil\\s*::\\bresult_of\\b)", "\\2util::invoke_result" },
95       { "(\\bNULL\\b)", "nullptr" },
96       // Boost preprocessor macros
97       { "\\b(BOOST_PP_CAT)\\b", "HPX_PP_CAT" },
98       { "\\b(BOOST_PP_STRINGIZE)\\b", "HPX_PP_STRINGIZE" },
99       { "\\b(BOOST_STRINGIZE)\\b", "HPX_PP_STRINGIZE(HPX_PP_EXPAND())" },
100       { "\\b(BOOST_ASSERT)\\b", "HPX_ASSERT" },
101       { nullptr, nullptr }
102     };
103 
104     //  deprecated_name_check constructor  --------------------------------- //
105 
deprecated_name_check()106     deprecated_name_check::deprecated_name_check()
107       : m_errors(0)
108     {
109       // C/C++ source code...
110       register_signature( ".c" );
111       register_signature( ".cpp" );
112       register_signature( ".cxx" );
113       register_signature( ".h" );
114       register_signature( ".hpp" );
115       register_signature( ".hxx" );
116       register_signature( ".inc" );
117       register_signature( ".ipp" );
118 
119       for (deprecated_names const* names_it = &names[0];
120            names_it->name_regex != nullptr;
121            ++names_it)
122       {
123         std::string rx(names_it->name_regex);
124         rx +=
125           "|"                   // or (ignored)
126           "("
127           "//[^\\n]*"           // single line comments (//)
128           "|"
129           "/\\*.*?\\*/"         // multi line comments (/**/)
130           "|"
131           "\"([^\"\\\\]|\\\\.)*\"" // string literals
132           ")";
133         regex_data.push_back(deprecated_names_regex_data(names_it, rx));
134       }
135     }
136 
137     //  inspect ( C++ source files )  ---------------------------------------//
138 
inspect(const string & library_name,const path & full_path,const string & contents)139     void deprecated_name_check::inspect(
140       const string & library_name,
141       const path & full_path,      // example: c:/foo/boost/filesystem/path.hpp
142       const string & contents)     // contents of file to be inspected
143     {
144       std::string::size_type p = contents.find( "hpxinspect:" "nodeprecatedname" );
145       if (p != string::npos)
146       {
147         // ignore this directive here (it is handled below) if it is followed
148         // by a ':'
149         if (p == contents.size() - 27 ||
150             (contents.size() > p + 27 && contents[p + 27] != ':'))
151         {
152           return;
153         }
154       }
155 
156       std::set<std::string> found_names;
157 
158       // for all given names, check whether any is used
159       for (deprecated_names_regex_data const& d : regex_data)
160       {
161         boost::sregex_iterator cur(contents.begin(), contents.end(), d.pattern), end;
162         for(/**/; cur != end; ++cur)
163         {
164           auto m = *cur;
165           if (m[1].matched)
166           {
167             // avoid errors to be reported twice
168             std::string found_name(m[1].first, m[1].second);
169 
170             if (found_names.find(found_name) == found_names.end())
171             {
172               std::string tag("hpxinspect:" "nodeprecatedname:" + found_name);
173               if (contents.find(tag) != string::npos)
174                 continue;
175 
176               // name was found
177               found_names.insert(found_name);
178 
179               auto it = contents.begin();
180               auto match_it = m[1].first;
181               auto line_start = it;
182 
183               string::size_type line_number = 1;
184               for (/**/; it != match_it; ++it)
185               {
186                 if (string::traits_type::eq(*it, '\n'))
187                 {
188                   ++line_number;
189                   line_start = it + 1; // could be end()
190                 }
191               }
192 
193               ++m_errors;
194               error(library_name, full_path, string(name())
195                   + " deprecated name ("
196                   + found_name
197                   + ") on line "
198                   + linelink(full_path, boost::lexical_cast<string>(line_number))
199                   + ", use " + m.format(d.data->use_instead)
200                   + " instead");
201             }
202           }
203         }
204       }
205     }
206 
207   } // namespace inspect
208 } // namespace boost
209 
210