name_scope_test.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/sem_ir/name_scope.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. namespace Carbon::SemIR {
  8. namespace {
  9. using ::testing::ElementsAre;
  10. using ::testing::Field;
  11. using ::testing::Pair;
  12. // NOLINTNEXTLINE(modernize-use-trailing-return-type): From the macro.
  13. MATCHER_P(NameScopeEntryEquals, entry, "") {
  14. return ExplainMatchResult(
  15. AllOf(Field("name_id", &NameScope::Entry::name_id, entry.name_id),
  16. Field("inst_id", &NameScope::Entry::inst_id, entry.inst_id),
  17. Field("access_kind", &NameScope::Entry::access_kind,
  18. entry.access_kind)),
  19. arg, result_listener);
  20. }
  21. TEST(NameScope, Empty) {
  22. int id = 0;
  23. InstId scope_inst_id(++id);
  24. NameId scope_name_id(++id);
  25. NameScopeId parent_scope_id(++id);
  26. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  27. EXPECT_THAT(name_scope.entries(), ElementsAre());
  28. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre());
  29. EXPECT_EQ(name_scope.inst_id(), scope_inst_id);
  30. EXPECT_EQ(name_scope.name_id(), scope_name_id);
  31. EXPECT_EQ(name_scope.parent_scope_id(), parent_scope_id);
  32. EXPECT_FALSE(name_scope.has_error());
  33. EXPECT_FALSE(name_scope.is_closed_import());
  34. EXPECT_FALSE(name_scope.is_imported_package());
  35. EXPECT_THAT(name_scope.import_ir_scopes(), ElementsAre());
  36. }
  37. TEST(NameScope, Lookup) {
  38. int id = 0;
  39. InstId scope_inst_id(++id);
  40. NameId scope_name_id(++id);
  41. NameScopeId parent_scope_id(++id);
  42. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  43. NameScope::Entry entry1 = {.name_id = NameId(++id),
  44. .inst_id = InstId(++id),
  45. .access_kind = AccessKind::Public};
  46. name_scope.AddRequired(entry1);
  47. NameScope::Entry entry2 = {.name_id = NameId(++id),
  48. .inst_id = InstId(++id),
  49. .access_kind = AccessKind::Protected};
  50. name_scope.AddRequired(entry2);
  51. NameScope::Entry entry3 = {.name_id = NameId(++id),
  52. .inst_id = InstId(++id),
  53. .access_kind = AccessKind::Private};
  54. name_scope.AddRequired(entry3);
  55. auto lookup = name_scope.Lookup(entry1.name_id);
  56. ASSERT_NE(lookup, std::nullopt);
  57. EXPECT_THAT(static_cast<NameScope&>(name_scope).GetEntry(*lookup),
  58. NameScopeEntryEquals(entry1));
  59. EXPECT_THAT(static_cast<const NameScope&>(name_scope).GetEntry(*lookup),
  60. NameScopeEntryEquals(entry1));
  61. lookup = name_scope.Lookup(entry2.name_id);
  62. ASSERT_NE(lookup, std::nullopt);
  63. EXPECT_THAT(name_scope.GetEntry(*lookup), NameScopeEntryEquals(entry2));
  64. lookup = name_scope.Lookup(entry3.name_id);
  65. ASSERT_NE(lookup, std::nullopt);
  66. EXPECT_THAT(name_scope.GetEntry(*lookup), NameScopeEntryEquals(entry3));
  67. NameId unknown_name_id(++id);
  68. lookup = name_scope.Lookup(unknown_name_id);
  69. EXPECT_EQ(lookup, std::nullopt);
  70. }
  71. TEST(NameScope, LookupOrAdd) {
  72. int id = 0;
  73. InstId scope_inst_id(++id);
  74. NameId scope_name_id(++id);
  75. NameScopeId parent_scope_id(++id);
  76. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  77. NameScope::Entry entry1 = {.name_id = NameId(++id),
  78. .inst_id = InstId(++id),
  79. .access_kind = AccessKind::Public};
  80. {
  81. auto [added, entry_id] = name_scope.LookupOrAdd(
  82. entry1.name_id, entry1.inst_id, entry1.access_kind);
  83. EXPECT_TRUE(added);
  84. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry1));
  85. }
  86. NameScope::Entry entry2 = {.name_id = NameId(++id),
  87. .inst_id = InstId(++id),
  88. .access_kind = AccessKind::Protected};
  89. {
  90. auto [added, entry_id] = name_scope.LookupOrAdd(
  91. entry2.name_id, entry2.inst_id, entry2.access_kind);
  92. EXPECT_TRUE(added);
  93. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry2));
  94. }
  95. NameScope::Entry entry3 = {.name_id = NameId(++id),
  96. .inst_id = InstId(++id),
  97. .access_kind = AccessKind::Private};
  98. {
  99. auto [added, entry_id] = name_scope.LookupOrAdd(
  100. entry3.name_id, entry3.inst_id, entry3.access_kind);
  101. EXPECT_TRUE(added);
  102. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry3));
  103. }
  104. {
  105. auto [added, entry_id] = name_scope.LookupOrAdd(
  106. entry1.name_id, entry1.inst_id, entry1.access_kind);
  107. EXPECT_FALSE(added);
  108. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry1));
  109. }
  110. {
  111. auto [added, entry_id] = name_scope.LookupOrAdd(
  112. entry2.name_id, entry2.inst_id, entry2.access_kind);
  113. EXPECT_FALSE(added);
  114. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry2));
  115. }
  116. {
  117. auto [added, entry_id] = name_scope.LookupOrAdd(
  118. entry3.name_id, entry3.inst_id, entry3.access_kind);
  119. EXPECT_FALSE(added);
  120. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry3));
  121. }
  122. }
  123. TEST(NameScope, Poison) {
  124. int id = 0;
  125. InstId scope_inst_id(++id);
  126. NameId scope_name_id(++id);
  127. NameScopeId parent_scope_id(++id);
  128. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  129. NameId poison1(++id);
  130. name_scope.AddPoison(poison1);
  131. EXPECT_THAT(name_scope.entries(),
  132. ElementsAre(NameScopeEntryEquals(
  133. NameScope::Entry({.name_id = poison1,
  134. .inst_id = InstId::Invalid,
  135. .access_kind = AccessKind::Public,
  136. .is_poisoned = true}))));
  137. NameId poison2(++id);
  138. name_scope.AddPoison(poison2);
  139. EXPECT_THAT(name_scope.entries(),
  140. ElementsAre(NameScopeEntryEquals(NameScope::Entry(
  141. {.name_id = poison1,
  142. .inst_id = InstId::Invalid,
  143. .access_kind = AccessKind::Public,
  144. .is_poisoned = true})),
  145. NameScopeEntryEquals(NameScope::Entry(
  146. {.name_id = poison2,
  147. .inst_id = InstId::Invalid,
  148. .access_kind = AccessKind::Public,
  149. .is_poisoned = true}))));
  150. auto lookup = name_scope.Lookup(poison1);
  151. ASSERT_NE(lookup, std::nullopt);
  152. EXPECT_THAT(
  153. name_scope.GetEntry(*lookup),
  154. NameScopeEntryEquals(NameScope::Entry({.name_id = poison1,
  155. .inst_id = InstId::Invalid,
  156. .access_kind = AccessKind::Public,
  157. .is_poisoned = true})));
  158. }
  159. TEST(NameScope, ExtendedScopes) {
  160. int id = 0;
  161. InstId scope_inst_id(++id);
  162. NameId scope_name_id(++id);
  163. NameScopeId parent_scope_id = NameScopeId::Package;
  164. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  165. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre());
  166. InstId extended_scope1(++id);
  167. name_scope.AddExtendedScope(extended_scope1);
  168. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre(extended_scope1));
  169. InstId extended_scope2(++id);
  170. name_scope.AddExtendedScope(extended_scope2);
  171. EXPECT_THAT(name_scope.extended_scopes(),
  172. ElementsAre(extended_scope1, extended_scope2));
  173. }
  174. TEST(NameScope, HasError) {
  175. int id = 0;
  176. InstId scope_inst_id(++id);
  177. NameId scope_name_id(++id);
  178. NameScopeId parent_scope_id(++id);
  179. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  180. EXPECT_FALSE(name_scope.has_error());
  181. name_scope.set_has_error();
  182. EXPECT_TRUE(name_scope.has_error());
  183. name_scope.set_has_error();
  184. EXPECT_TRUE(name_scope.has_error());
  185. }
  186. TEST(NameScope, IsClosedImport) {
  187. int id = 0;
  188. InstId scope_inst_id(++id);
  189. NameId scope_name_id(++id);
  190. NameScopeId parent_scope_id(++id);
  191. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  192. EXPECT_FALSE(name_scope.is_closed_import());
  193. name_scope.set_is_closed_import(true);
  194. EXPECT_TRUE(name_scope.is_closed_import());
  195. name_scope.set_is_closed_import(false);
  196. EXPECT_FALSE(name_scope.is_closed_import());
  197. }
  198. TEST(NameScope, IsImportedPackageParentNonPackageScope) {
  199. int id = 0;
  200. InstId scope_inst_id(++id);
  201. NameId scope_name_id(++id);
  202. NameScopeId parent_scope_id(++id);
  203. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  204. EXPECT_FALSE(name_scope.is_imported_package());
  205. name_scope.set_is_closed_import(true);
  206. EXPECT_FALSE(name_scope.is_imported_package());
  207. name_scope.set_is_closed_import(false);
  208. EXPECT_FALSE(name_scope.is_imported_package());
  209. }
  210. TEST(NameScope, IsImportedPackageParentPackageScope) {
  211. int id = 0;
  212. InstId scope_inst_id(++id);
  213. NameId scope_name_id(++id);
  214. NameScopeId parent_scope_id = NameScopeId::Package;
  215. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  216. EXPECT_FALSE(name_scope.is_imported_package());
  217. name_scope.set_is_closed_import(true);
  218. EXPECT_TRUE(name_scope.is_imported_package());
  219. name_scope.set_is_closed_import(false);
  220. EXPECT_FALSE(name_scope.is_imported_package());
  221. }
  222. TEST(NameScope, ImportIRScopes) {
  223. int id = 0;
  224. InstId scope_inst_id(++id);
  225. NameId scope_name_id(++id);
  226. NameScopeId parent_scope_id = NameScopeId::Package;
  227. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  228. EXPECT_THAT(name_scope.import_ir_scopes(), ElementsAre());
  229. ImportIRId import_ir_id1(++id);
  230. NameScopeId import_name_scope_id1(++id);
  231. name_scope.AddImportIRScope({import_ir_id1, import_name_scope_id1});
  232. EXPECT_THAT(name_scope.import_ir_scopes(),
  233. ElementsAre(Pair(import_ir_id1, import_name_scope_id1)));
  234. ImportIRId import_ir_id2(++id);
  235. NameScopeId import_name_scope_id2(++id);
  236. name_scope.AddImportIRScope({import_ir_id2, import_name_scope_id2});
  237. EXPECT_THAT(name_scope.import_ir_scopes(),
  238. ElementsAre(Pair(import_ir_id1, import_name_scope_id1),
  239. Pair(import_ir_id2, import_name_scope_id2)));
  240. }
  241. } // namespace
  242. } // namespace Carbon::SemIR