name_scope_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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, LookupOrPoison) {
  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. name_scope.AddRequired(entry1);
  81. NameScope::Entry entry2 = {.name_id = NameId(++id),
  82. .inst_id = InstId(++id),
  83. .access_kind = AccessKind::Protected};
  84. name_scope.AddRequired(entry2);
  85. NameScope::Entry entry3 = {.name_id = NameId(++id),
  86. .inst_id = InstId(++id),
  87. .access_kind = AccessKind::Private};
  88. name_scope.AddRequired(entry3);
  89. auto lookup = name_scope.LookupOrPoison(entry1.name_id);
  90. ASSERT_NE(lookup, std::nullopt);
  91. EXPECT_THAT(static_cast<NameScope&>(name_scope).GetEntry(*lookup),
  92. NameScopeEntryEquals(entry1));
  93. EXPECT_THAT(static_cast<const NameScope&>(name_scope).GetEntry(*lookup),
  94. NameScopeEntryEquals(entry1));
  95. lookup = name_scope.LookupOrPoison(entry2.name_id);
  96. ASSERT_NE(lookup, std::nullopt);
  97. EXPECT_THAT(name_scope.GetEntry(*lookup), NameScopeEntryEquals(entry2));
  98. lookup = name_scope.LookupOrPoison(entry3.name_id);
  99. ASSERT_NE(lookup, std::nullopt);
  100. EXPECT_THAT(name_scope.GetEntry(*lookup), NameScopeEntryEquals(entry3));
  101. NameId unknown_name_id(++id);
  102. lookup = name_scope.LookupOrPoison(unknown_name_id);
  103. EXPECT_EQ(lookup, std::nullopt);
  104. }
  105. TEST(NameScope, LookupOrAdd) {
  106. int id = 0;
  107. InstId scope_inst_id(++id);
  108. NameId scope_name_id(++id);
  109. NameScopeId parent_scope_id(++id);
  110. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  111. NameScope::Entry entry1 = {.name_id = NameId(++id),
  112. .inst_id = InstId(++id),
  113. .access_kind = AccessKind::Public};
  114. {
  115. auto [added, entry_id] = name_scope.LookupOrAdd(
  116. entry1.name_id, entry1.inst_id, entry1.access_kind);
  117. EXPECT_TRUE(added);
  118. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry1));
  119. }
  120. NameScope::Entry entry2 = {.name_id = NameId(++id),
  121. .inst_id = InstId(++id),
  122. .access_kind = AccessKind::Protected};
  123. {
  124. auto [added, entry_id] = name_scope.LookupOrAdd(
  125. entry2.name_id, entry2.inst_id, entry2.access_kind);
  126. EXPECT_TRUE(added);
  127. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry2));
  128. }
  129. NameScope::Entry entry3 = {.name_id = NameId(++id),
  130. .inst_id = InstId(++id),
  131. .access_kind = AccessKind::Private};
  132. {
  133. auto [added, entry_id] = name_scope.LookupOrAdd(
  134. entry3.name_id, entry3.inst_id, entry3.access_kind);
  135. EXPECT_TRUE(added);
  136. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry3));
  137. }
  138. {
  139. auto [added, entry_id] = name_scope.LookupOrAdd(
  140. entry1.name_id, entry1.inst_id, entry1.access_kind);
  141. EXPECT_FALSE(added);
  142. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry1));
  143. }
  144. {
  145. auto [added, entry_id] = name_scope.LookupOrAdd(
  146. entry2.name_id, entry2.inst_id, entry2.access_kind);
  147. EXPECT_FALSE(added);
  148. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry2));
  149. }
  150. {
  151. auto [added, entry_id] = name_scope.LookupOrAdd(
  152. entry3.name_id, entry3.inst_id, entry3.access_kind);
  153. EXPECT_FALSE(added);
  154. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry3));
  155. }
  156. }
  157. TEST(NameScope, Poison) {
  158. int id = 0;
  159. InstId scope_inst_id(++id);
  160. NameId scope_name_id(++id);
  161. NameScopeId parent_scope_id(++id);
  162. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  163. NameId poison1(++id);
  164. EXPECT_EQ(name_scope.LookupOrPoison(poison1), std::nullopt);
  165. EXPECT_THAT(name_scope.entries(),
  166. ElementsAre(NameScopeEntryEquals(
  167. NameScope::Entry({.name_id = poison1,
  168. .inst_id = InstId::Invalid,
  169. .access_kind = AccessKind::Public,
  170. .is_poisoned = true}))));
  171. NameId poison2(++id);
  172. EXPECT_EQ(name_scope.LookupOrPoison(poison2), std::nullopt);
  173. EXPECT_THAT(name_scope.entries(),
  174. ElementsAre(NameScopeEntryEquals(NameScope::Entry(
  175. {.name_id = poison1,
  176. .inst_id = InstId::Invalid,
  177. .access_kind = AccessKind::Public,
  178. .is_poisoned = true})),
  179. NameScopeEntryEquals(NameScope::Entry(
  180. {.name_id = poison2,
  181. .inst_id = InstId::Invalid,
  182. .access_kind = AccessKind::Public,
  183. .is_poisoned = true}))));
  184. auto lookup = name_scope.Lookup(poison1);
  185. ASSERT_NE(lookup, std::nullopt);
  186. EXPECT_THAT(
  187. name_scope.GetEntry(*lookup),
  188. NameScopeEntryEquals(NameScope::Entry({.name_id = poison1,
  189. .inst_id = InstId::Invalid,
  190. .access_kind = AccessKind::Public,
  191. .is_poisoned = true})));
  192. }
  193. TEST(NameScope, AddRequiredAfterPoison) {
  194. int id = 0;
  195. InstId scope_inst_id(++id);
  196. NameId scope_name_id(++id);
  197. NameScopeId parent_scope_id(++id);
  198. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  199. NameId name_id(++id);
  200. InstId inst_id(++id);
  201. EXPECT_EQ(name_scope.LookupOrPoison(name_id), std::nullopt);
  202. EXPECT_THAT(name_scope.entries(),
  203. ElementsAre(NameScopeEntryEquals(
  204. NameScope::Entry({.name_id = name_id,
  205. .inst_id = InstId::Invalid,
  206. .access_kind = AccessKind::Public,
  207. .is_poisoned = true}))));
  208. NameScope::Entry entry = {.name_id = name_id,
  209. .inst_id = inst_id,
  210. .access_kind = AccessKind::Private};
  211. name_scope.AddRequired(entry);
  212. auto lookup = name_scope.LookupOrPoison(name_id);
  213. ASSERT_NE(lookup, std::nullopt);
  214. EXPECT_THAT(
  215. name_scope.GetEntry(*lookup),
  216. NameScopeEntryEquals(NameScope::Entry({.name_id = name_id,
  217. .inst_id = inst_id,
  218. .access_kind = AccessKind::Private,
  219. .is_poisoned = false})));
  220. }
  221. TEST(NameScope, ExtendedScopes) {
  222. int id = 0;
  223. InstId scope_inst_id(++id);
  224. NameId scope_name_id(++id);
  225. NameScopeId parent_scope_id = NameScopeId::Package;
  226. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  227. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre());
  228. InstId extended_scope1(++id);
  229. name_scope.AddExtendedScope(extended_scope1);
  230. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre(extended_scope1));
  231. InstId extended_scope2(++id);
  232. name_scope.AddExtendedScope(extended_scope2);
  233. EXPECT_THAT(name_scope.extended_scopes(),
  234. ElementsAre(extended_scope1, extended_scope2));
  235. }
  236. TEST(NameScope, HasError) {
  237. int id = 0;
  238. InstId scope_inst_id(++id);
  239. NameId scope_name_id(++id);
  240. NameScopeId parent_scope_id(++id);
  241. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  242. EXPECT_FALSE(name_scope.has_error());
  243. name_scope.set_has_error();
  244. EXPECT_TRUE(name_scope.has_error());
  245. name_scope.set_has_error();
  246. EXPECT_TRUE(name_scope.has_error());
  247. }
  248. TEST(NameScope, IsClosedImport) {
  249. int id = 0;
  250. InstId scope_inst_id(++id);
  251. NameId scope_name_id(++id);
  252. NameScopeId parent_scope_id(++id);
  253. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  254. EXPECT_FALSE(name_scope.is_closed_import());
  255. name_scope.set_is_closed_import(true);
  256. EXPECT_TRUE(name_scope.is_closed_import());
  257. name_scope.set_is_closed_import(false);
  258. EXPECT_FALSE(name_scope.is_closed_import());
  259. }
  260. TEST(NameScope, IsImportedPackageParentNonPackageScope) {
  261. int id = 0;
  262. InstId scope_inst_id(++id);
  263. NameId scope_name_id(++id);
  264. NameScopeId parent_scope_id(++id);
  265. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  266. EXPECT_FALSE(name_scope.is_imported_package());
  267. name_scope.set_is_closed_import(true);
  268. EXPECT_FALSE(name_scope.is_imported_package());
  269. name_scope.set_is_closed_import(false);
  270. EXPECT_FALSE(name_scope.is_imported_package());
  271. }
  272. TEST(NameScope, IsImportedPackageParentPackageScope) {
  273. int id = 0;
  274. InstId scope_inst_id(++id);
  275. NameId scope_name_id(++id);
  276. NameScopeId parent_scope_id = NameScopeId::Package;
  277. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  278. EXPECT_FALSE(name_scope.is_imported_package());
  279. name_scope.set_is_closed_import(true);
  280. EXPECT_TRUE(name_scope.is_imported_package());
  281. name_scope.set_is_closed_import(false);
  282. EXPECT_FALSE(name_scope.is_imported_package());
  283. }
  284. TEST(NameScope, ImportIRScopes) {
  285. int id = 0;
  286. InstId scope_inst_id(++id);
  287. NameId scope_name_id(++id);
  288. NameScopeId parent_scope_id = NameScopeId::Package;
  289. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  290. EXPECT_THAT(name_scope.import_ir_scopes(), ElementsAre());
  291. ImportIRId import_ir_id1(++id);
  292. NameScopeId import_name_scope_id1(++id);
  293. name_scope.AddImportIRScope({import_ir_id1, import_name_scope_id1});
  294. EXPECT_THAT(name_scope.import_ir_scopes(),
  295. ElementsAre(Pair(import_ir_id1, import_name_scope_id1)));
  296. ImportIRId import_ir_id2(++id);
  297. NameScopeId import_name_scope_id2(++id);
  298. name_scope.AddImportIRScope({import_ir_id2, import_name_scope_id2});
  299. EXPECT_THAT(name_scope.import_ir_scopes(),
  300. ElementsAre(Pair(import_ir_id1, import_name_scope_id1),
  301. Pair(import_ir_id2, import_name_scope_id2)));
  302. }
  303. } // namespace
  304. } // namespace Carbon::SemIR