2011-02-04 22:28:15 +00:00
|
|
|
//===--- iwyu_stl_util.h - STL-like utilities for include-what-you-use ----===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// Utilities that make it easier to work with STL.
|
|
|
|
|
2016-05-22 09:06:36 +01:00
|
|
|
#ifndef INCLUDE_WHAT_YOU_USE_IWYU_STL_UTIL_H_
|
|
|
|
#define INCLUDE_WHAT_YOU_USE_IWYU_STL_UTIL_H_
|
2011-02-04 22:28:15 +00:00
|
|
|
|
2011-05-04 19:30:53 +01:00
|
|
|
#include <algorithm> // for find
|
|
|
|
#include <map> // for map, multimap
|
|
|
|
#include <set> // for set
|
|
|
|
#include <vector> // for vector
|
2011-05-04 19:29:59 +01:00
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
namespace include_what_you_use {
|
|
|
|
|
|
|
|
using std::map;
|
|
|
|
using std::set;
|
|
|
|
using std::vector;
|
|
|
|
|
2011-04-27 00:01:59 +01:00
|
|
|
// Returns true if the associative container (e.g. set or map)
|
|
|
|
// contains the given key.
|
|
|
|
template <class AssociativeContainer>
|
2011-04-27 00:02:58 +01:00
|
|
|
bool ContainsKey(const AssociativeContainer& container,
|
|
|
|
const typename AssociativeContainer::key_type& key) {
|
2011-02-04 22:28:15 +00:00
|
|
|
return container.find(key) != container.end();
|
|
|
|
}
|
|
|
|
|
2011-04-27 00:01:59 +01:00
|
|
|
// Returns true if the container contains the given value.
|
|
|
|
template <class Container>
|
|
|
|
bool ContainsValue(const Container& container,
|
|
|
|
const typename Container::value_type& value) {
|
|
|
|
return (std::find(container.begin(), container.end(), value)
|
|
|
|
!= container.end());
|
|
|
|
}
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
// For maps, we also let you check if the key exists with the given value.
|
|
|
|
template <class Container, typename K, typename V>
|
|
|
|
bool ContainsKeyValue(const Container& container,
|
|
|
|
const K& key, const V& value) {
|
|
|
|
for (typename Container::const_iterator it = container.lower_bound(key),
|
|
|
|
end = container.upper_bound(key); it != end; ++it) {
|
|
|
|
if (it->second == value)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
iwyu was egregiously wrong in how it handled template
arguments using the 'precomputed cache'. In such situations,
it totally ignored the currently active resugar_map, replacing
it with one of its own. That worked fine for types outside of
templates, but not fine for types inside (such as a 'hash_map<T>'
inside a templated class).
I "fixed" this. "Fixed" is in quotes because this turned up a
whole slew of other problems I don't even attempt to resolve
here (though I spent a few hours trying). One is that it's
possible to have a type like hash_map that has some arguments
that are dependent and some that aren't; in theory, for these
types, we can correctly attribute the use to the template
author or template instantiator depending on which type it
is. But I can't figure out how to get clang to do any
meaningful analysis of incomplete (dependent) types, so I've
punted on that for now.
The second thing wrong is I jumped through all sorts of hoops
to handle default template arguments correctly, so if a class
has a hash_map<T> and you instantiate T with string, you're
also made responsible for hash<string>. This *should* work,
but clang is giving hash<string> a type I don't expect
(RecordType, not TemplateSpecializationType), and I don't know
how to deal with that -- I don't know how to extract the
'string' part of this RecordType. Ugh. I punt on this now,
as well.
Even in this incomplete form, it's enough to resolve a P1 bug,
so I figure it's worth putting in.
R=dsturtevant
DELTA=141 (97 added, 7 deleted, 37 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=3147
2011-08-31 12:42:23 +01:00
|
|
|
// Returns true if the associative container contains any key in the
|
|
|
|
// given set.
|
|
|
|
template <class AssociativeContainer>
|
|
|
|
bool ContainsAnyKey(
|
|
|
|
const AssociativeContainer& container,
|
|
|
|
const set<typename AssociativeContainer::key_type>& keys) {
|
2016-06-02 00:43:00 +01:00
|
|
|
for (const auto& key : keys) {
|
|
|
|
if (ContainsKey(container, key))
|
iwyu was egregiously wrong in how it handled template
arguments using the 'precomputed cache'. In such situations,
it totally ignored the currently active resugar_map, replacing
it with one of its own. That worked fine for types outside of
templates, but not fine for types inside (such as a 'hash_map<T>'
inside a templated class).
I "fixed" this. "Fixed" is in quotes because this turned up a
whole slew of other problems I don't even attempt to resolve
here (though I spent a few hours trying). One is that it's
possible to have a type like hash_map that has some arguments
that are dependent and some that aren't; in theory, for these
types, we can correctly attribute the use to the template
author or template instantiator depending on which type it
is. But I can't figure out how to get clang to do any
meaningful analysis of incomplete (dependent) types, so I've
punted on that for now.
The second thing wrong is I jumped through all sorts of hoops
to handle default template arguments correctly, so if a class
has a hash_map<T> and you instantiate T with string, you're
also made responsible for hash<string>. This *should* work,
but clang is giving hash<string> a type I don't expect
(RecordType, not TemplateSpecializationType), and I don't know
how to deal with that -- I don't know how to extract the
'string' part of this RecordType. Ugh. I punt on this now,
as well.
Even in this incomplete form, it's enough to resolve a P1 bug,
so I figure it's worth putting in.
R=dsturtevant
DELTA=141 (97 added, 7 deleted, 37 changed)
Revision created by MOE tool push_codebase.
MOE_MIGRATION=3147
2011-08-31 12:42:23 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
// Returns a_map[key] if key is in a_map; otherwise returns default_value.
|
|
|
|
template <class Map>
|
|
|
|
const typename Map::mapped_type& GetOrDefault(
|
|
|
|
const Map& a_map, const typename Map::key_type& key,
|
|
|
|
const typename Map::mapped_type& default_value) {
|
2011-04-27 00:02:58 +01:00
|
|
|
if (ContainsKey(a_map, key))
|
2011-02-04 22:28:15 +00:00
|
|
|
return a_map.find(key)->second;
|
|
|
|
return default_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a pointer to (*a_map)[key] if key is in *a_map; otherwise
|
2016-06-02 00:43:00 +01:00
|
|
|
// returns nullptr.
|
2011-02-04 22:28:15 +00:00
|
|
|
template <typename K, typename V>
|
|
|
|
const V* FindInMap(const map<K, V>* a_map, const K& key) {
|
|
|
|
const typename map<K, V>::const_iterator it = a_map->find(key);
|
2016-06-02 00:43:00 +01:00
|
|
|
return it == a_map->end() ? nullptr : &it->second;
|
2011-02-04 22:28:15 +00:00
|
|
|
}
|
|
|
|
template <typename K, typename V>
|
|
|
|
V* FindInMap(map<K, V>* a_map, const K& key) {
|
|
|
|
const typename map<K, V>::iterator it = a_map->find(key);
|
2016-06-02 00:43:00 +01:00
|
|
|
return it == a_map->end() ? nullptr : &it->second;
|
2011-02-04 22:28:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Removes all elements in source from target.
|
|
|
|
template <class SourceContainer, class TargetContainer>
|
|
|
|
void RemoveAllFrom(const SourceContainer& source, TargetContainer* target) {
|
|
|
|
for (typename SourceContainer::const_iterator it = source.begin();
|
|
|
|
it != source.end(); ++it) {
|
|
|
|
target->erase(*it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Inserts all elements from source into target.
|
|
|
|
template <class SourceContainer, class TargetContainer>
|
|
|
|
void InsertAllInto(const SourceContainer& source, TargetContainer* target) {
|
|
|
|
target->insert(source.begin(), source.end());
|
|
|
|
}
|
|
|
|
|
2011-03-04 00:22:18 +00:00
|
|
|
// Appends all elements from source to the end of target. The target
|
|
|
|
// type must support inserting a range at the end, which probably
|
|
|
|
// means it's a vector.
|
|
|
|
template <class TargetContainer, class SourceContainer>
|
|
|
|
void Extend(TargetContainer* target, const SourceContainer& source) {
|
|
|
|
target->insert(target->end(), source.begin(), source.end());
|
|
|
|
}
|
|
|
|
|
2011-02-04 22:28:15 +00:00
|
|
|
// Returns the union of the two given sets.
|
|
|
|
template <typename T>
|
|
|
|
set<T> Union(const set<T>& lhs, const set<T>& rhs) {
|
|
|
|
set<T> retval(lhs);
|
|
|
|
InsertAllInto(rhs, &retval);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a vector v with all duplicates removed, but order otherwise
|
|
|
|
// maintained.
|
|
|
|
template <typename T>
|
|
|
|
vector<T> GetUniqueEntries(const vector<T>& v) {
|
|
|
|
set<T> seen;
|
|
|
|
vector<T> retval;
|
|
|
|
for (typename vector<T>::const_iterator it = v.begin(); it != v.end(); ++it) {
|
2011-04-27 00:02:58 +01:00
|
|
|
if (!ContainsKey(seen, *it)) {
|
2011-02-04 22:28:15 +00:00
|
|
|
retval.push_back(*it);
|
|
|
|
seen.insert(*it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace include_what_you_use
|
|
|
|
|
2016-05-22 09:06:36 +01:00
|
|
|
#endif // INCLUDE_WHAT_YOU_USE_IWYU_STL_UTIL_H_
|