| // Part of the Crubit project, under the Apache License v2.0 with LLVM |
| // Exceptions. See /LICENSE for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| |
| #include "lifetime_annotations/lifetime_symbol_table.h" |
| |
| #include <cassert> |
| #include <cstddef> |
| #include <optional> |
| #include <string> |
| |
| #include "lifetime_annotations/lifetime.h" |
| #include "llvm/Support/ErrorHandling.h" |
| |
| namespace clang { |
| namespace tidy { |
| namespace lifetimes { |
| |
| std::optional<Lifetime> LifetimeSymbolTable::LookupName( |
| llvm::StringRef name) const { |
| if (name == "static") { |
| return Lifetime::Static(); |
| } |
| |
| auto iter = name_to_lifetime_.find(name); |
| if (iter == name_to_lifetime_.end()) { |
| return std::nullopt; |
| } |
| return iter->second; |
| } |
| |
| Lifetime LifetimeSymbolTable::LookupNameAndMaybeDeclare(llvm::StringRef name) { |
| if (name == "static") { |
| return Lifetime::Static(); |
| } |
| |
| auto [iter, inserted] = |
| name_to_lifetime_.try_emplace(name, Lifetime::Static()); |
| if (inserted) { |
| Lifetime lifetime = Lifetime::CreateVariable(); |
| iter->second = lifetime; |
| assert(!lifetime_to_name_.count(lifetime)); |
| lifetime_to_name_[lifetime] = name; |
| } |
| return iter->second; |
| } |
| |
| std::optional<llvm::StringRef> LifetimeSymbolTable::LookupLifetime( |
| Lifetime lifetime) const { |
| if (lifetime == Lifetime::Static()) { |
| return "static"; |
| } |
| |
| auto iter = lifetime_to_name_.find(lifetime); |
| if (iter == lifetime_to_name_.end()) { |
| return std::nullopt; |
| } |
| return iter->second; |
| } |
| |
| static std::string NameFromIndex(int index) { |
| int num_chars = 1; |
| // Number of combinations that are possible with `num_chars` characters. |
| int num_combinations = 26; |
| while (index >= num_combinations) { |
| index -= num_combinations; |
| ++num_chars; |
| num_combinations *= 26; |
| } |
| std::string name; |
| name.reserve(num_chars); |
| for (int i = 0; i < num_chars; ++i) { |
| name.insert(0, static_cast<size_t>(1), 'a' + index % 26); |
| index /= 26; |
| } |
| return name; |
| } |
| |
| llvm::StringRef LifetimeSymbolTable::LookupLifetimeAndMaybeDeclare( |
| Lifetime lifetime) { |
| if (lifetime == Lifetime::Static()) { |
| return "static"; |
| } |
| |
| auto lifetime_to_name_iter = lifetime_to_name_.find(lifetime); |
| if (lifetime_to_name_iter != lifetime_to_name_.end()) { |
| return lifetime_to_name_iter->second; |
| } |
| |
| while (true) { |
| std::string name = NameFromIndex(next_name_index_++); |
| auto [name_to_lifetime_iter, inserted] = |
| name_to_lifetime_.try_emplace(name, lifetime); |
| if (inserted) { |
| lifetime_to_name_[lifetime] = name; |
| return name_to_lifetime_iter->first(); |
| } |
| } |
| } |
| |
| void LifetimeSymbolTable::Add(llvm::StringRef name, Lifetime lifetime) { |
| auto [_, inserted] = name_to_lifetime_.try_emplace(name, lifetime); |
| if (!inserted) { |
| llvm::report_fatal_error("duplicate lifetime parameter"); |
| } |
| lifetime_to_name_[lifetime] = name; |
| } |
| |
| void LifetimeSymbolTable::Rebind(llvm::StringRef name, Lifetime lifetime) { |
| auto iter = name_to_lifetime_.find(name); |
| if (iter == name_to_lifetime_.end()) { |
| llvm::report_fatal_error("invalid call to rebind"); |
| } |
| lifetime_to_name_.erase(iter->second); |
| lifetime_to_name_[lifetime] = name; |
| iter->second = lifetime; |
| } |
| |
| } // namespace lifetimes |
| } // namespace tidy |
| } // namespace clang |