DependenceFlags.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- DependenceFlags.h ------------------------------------------------===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_CLANG_AST_DEPENDENCEFLAGS_H
  14. #define LLVM_CLANG_AST_DEPENDENCEFLAGS_H
  15. #include "clang/Basic/BitmaskEnum.h"
  16. #include "llvm/ADT/BitmaskEnum.h"
  17. #include <cstdint>
  18. namespace clang {
  19. struct ExprDependenceScope {
  20. enum ExprDependence : uint8_t {
  21. UnexpandedPack = 1,
  22. // This expr depends in any way on
  23. // - a template parameter, it implies that the resolution of this expr may
  24. // cause instantiation to fail
  25. // - or an error (often in a non-template context)
  26. //
  27. // Note that C++ standard doesn't define the instantiation-dependent term,
  28. // we follow the formal definition coming from the Itanium C++ ABI, and
  29. // extend it to errors.
  30. Instantiation = 2,
  31. // The type of this expr depends on a template parameter, or an error.
  32. Type = 4,
  33. // The value of this expr depends on a template parameter, or an error.
  34. Value = 8,
  35. // clang extension: this expr contains or references an error, and is
  36. // considered dependent on how that error is resolved.
  37. Error = 16,
  38. None = 0,
  39. All = 31,
  40. TypeValue = Type | Value,
  41. TypeInstantiation = Type | Instantiation,
  42. ValueInstantiation = Value | Instantiation,
  43. TypeValueInstantiation = Type | Value | Instantiation,
  44. ErrorDependent = Error | ValueInstantiation,
  45. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
  46. };
  47. };
  48. using ExprDependence = ExprDependenceScope::ExprDependence;
  49. struct TypeDependenceScope {
  50. enum TypeDependence : uint8_t {
  51. /// Whether this type contains an unexpanded parameter pack
  52. /// (for C++11 variadic templates)
  53. UnexpandedPack = 1,
  54. /// Whether this type somehow involves
  55. /// - a template parameter, even if the resolution of the type does not
  56. /// depend on a template parameter.
  57. /// - or an error.
  58. Instantiation = 2,
  59. /// Whether this type
  60. /// - is a dependent type (C++ [temp.dep.type])
  61. /// - or it somehow involves an error, e.g. decltype(recovery-expr)
  62. Dependent = 4,
  63. /// Whether this type is a variably-modified type (C99 6.7.5).
  64. VariablyModified = 8,
  65. /// Whether this type references an error, e.g. decltype(err-expression)
  66. /// yields an error type.
  67. Error = 16,
  68. None = 0,
  69. All = 31,
  70. DependentInstantiation = Dependent | Instantiation,
  71. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
  72. };
  73. };
  74. using TypeDependence = TypeDependenceScope::TypeDependence;
  75. #define LLVM_COMMON_DEPENDENCE(NAME) \
  76. struct NAME##Scope { \
  77. enum NAME : uint8_t { \
  78. UnexpandedPack = 1, \
  79. Instantiation = 2, \
  80. Dependent = 4, \
  81. Error = 8, \
  82. \
  83. None = 0, \
  84. DependentInstantiation = Dependent | Instantiation, \
  85. All = 15, \
  86. \
  87. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) \
  88. }; \
  89. }; \
  90. using NAME = NAME##Scope::NAME;
  91. LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence)
  92. LLVM_COMMON_DEPENDENCE(TemplateNameDependence)
  93. LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence)
  94. #undef LLVM_COMMON_DEPENDENCE
  95. // A combined space of all dependence concepts for all node types.
  96. // Used when aggregating dependence of nodes of different types.
  97. class Dependence {
  98. public:
  99. enum Bits : uint8_t {
  100. None = 0,
  101. // Contains a template parameter pack that wasn't expanded.
  102. UnexpandedPack = 1,
  103. // Depends on a template parameter or an error in some way.
  104. // Validity depends on how the template is instantiated or the error is
  105. // resolved.
  106. Instantiation = 2,
  107. // Expression type depends on template context, or an error.
  108. // Value and Instantiation should also be set.
  109. Type = 4,
  110. // Expression value depends on template context, or an error.
  111. // Instantiation should also be set.
  112. Value = 8,
  113. // Depends on template context, or an error.
  114. // The type/value distinction is only meaningful for expressions.
  115. Dependent = Type | Value,
  116. // Includes an error, and depends on how it is resolved.
  117. Error = 16,
  118. // Type depends on a runtime value (variable-length array).
  119. VariablyModified = 32,
  120. // Dependence that is propagated syntactically, regardless of semantics.
  121. Syntactic = UnexpandedPack | Instantiation | Error,
  122. LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
  123. };
  124. Dependence() : V(None) {}
  125. Dependence(TypeDependence D)
  126. : V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) |
  127. translate(D, TypeDependence::Instantiation, Instantiation) |
  128. translate(D, TypeDependence::Dependent, Dependent) |
  129. translate(D, TypeDependence::Error, Error) |
  130. translate(D, TypeDependence::VariablyModified, VariablyModified)) {}
  131. Dependence(ExprDependence D)
  132. : V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) |
  133. translate(D, ExprDependence::Instantiation, Instantiation) |
  134. translate(D, ExprDependence::Type, Type) |
  135. translate(D, ExprDependence::Value, Value) |
  136. translate(D, ExprDependence::Error, Error)) {}
  137. Dependence(NestedNameSpecifierDependence D) :
  138. V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) |
  139. translate(D, NNSDependence::Instantiation, Instantiation) |
  140. translate(D, NNSDependence::Dependent, Dependent) |
  141. translate(D, NNSDependence::Error, Error)) {}
  142. Dependence(TemplateArgumentDependence D)
  143. : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) |
  144. translate(D, TADependence::Instantiation, Instantiation) |
  145. translate(D, TADependence::Dependent, Dependent) |
  146. translate(D, TADependence::Error, Error)) {}
  147. Dependence(TemplateNameDependence D)
  148. : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) |
  149. translate(D, TNDependence::Instantiation, Instantiation) |
  150. translate(D, TNDependence::Dependent, Dependent) |
  151. translate(D, TNDependence::Error, Error)) {}
  152. /// Extract only the syntactic portions of this type's dependence.
  153. Dependence syntactic() {
  154. Dependence Result = *this;
  155. Result.V &= Syntactic;
  156. return Result;
  157. }
  158. TypeDependence type() const {
  159. return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
  160. translate(V, Instantiation, TypeDependence::Instantiation) |
  161. translate(V, Dependent, TypeDependence::Dependent) |
  162. translate(V, Error, TypeDependence::Error) |
  163. translate(V, VariablyModified, TypeDependence::VariablyModified);
  164. }
  165. ExprDependence expr() const {
  166. return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) |
  167. translate(V, Instantiation, ExprDependence::Instantiation) |
  168. translate(V, Type, ExprDependence::Type) |
  169. translate(V, Value, ExprDependence::Value) |
  170. translate(V, Error, ExprDependence::Error);
  171. }
  172. NestedNameSpecifierDependence nestedNameSpecifier() const {
  173. return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) |
  174. translate(V, Instantiation, NNSDependence::Instantiation) |
  175. translate(V, Dependent, NNSDependence::Dependent) |
  176. translate(V, Error, NNSDependence::Error);
  177. }
  178. TemplateArgumentDependence templateArgument() const {
  179. return translate(V, UnexpandedPack, TADependence::UnexpandedPack) |
  180. translate(V, Instantiation, TADependence::Instantiation) |
  181. translate(V, Dependent, TADependence::Dependent) |
  182. translate(V, Error, TADependence::Error);
  183. }
  184. TemplateNameDependence templateName() const {
  185. return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) |
  186. translate(V, Instantiation, TNDependence::Instantiation) |
  187. translate(V, Dependent, TNDependence::Dependent) |
  188. translate(V, Error, TNDependence::Error);
  189. }
  190. private:
  191. Bits V;
  192. template <typename T, typename U>
  193. static U translate(T Bits, T FromBit, U ToBit) {
  194. return (Bits & FromBit) ? ToBit : static_cast<U>(0);
  195. }
  196. // Abbreviations to make conversions more readable.
  197. using NNSDependence = NestedNameSpecifierDependence;
  198. using TADependence = TemplateArgumentDependence;
  199. using TNDependence = TemplateNameDependence;
  200. };
  201. /// Computes dependencies of a reference with the name having template arguments
  202. /// with \p TA dependencies.
  203. inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
  204. return Dependence(TA).expr();
  205. }
  206. inline ExprDependence toExprDependence(TypeDependence D) {
  207. return Dependence(D).expr();
  208. }
  209. // Note: it's often necessary to strip `Dependent` from qualifiers.
  210. // If V<T>:: refers to the current instantiation, NNS is considered dependent
  211. // but the containing V<T>::foo likely isn't.
  212. inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
  213. return Dependence(D).expr();
  214. }
  215. inline ExprDependence turnTypeToValueDependence(ExprDependence D) {
  216. // Type-dependent expressions are always be value-dependent, so we simply drop
  217. // type dependency.
  218. return D & ~ExprDependence::Type;
  219. }
  220. inline ExprDependence turnValueToTypeDependence(ExprDependence D) {
  221. // Type-dependent expressions are always be value-dependent.
  222. if (D & ExprDependence::Value)
  223. D |= ExprDependence::Type;
  224. return D;
  225. }
  226. // Returned type-dependence will never have VariablyModified set.
  227. inline TypeDependence toTypeDependence(ExprDependence D) {
  228. return Dependence(D).type();
  229. }
  230. inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
  231. return Dependence(D).type();
  232. }
  233. inline TypeDependence toTypeDependence(TemplateNameDependence D) {
  234. return Dependence(D).type();
  235. }
  236. inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
  237. return Dependence(D).type();
  238. }
  239. inline TypeDependence toSyntacticDependence(TypeDependence D) {
  240. return Dependence(D).syntactic().type();
  241. }
  242. inline NestedNameSpecifierDependence
  243. toNestedNameSpecifierDependendence(TypeDependence D) {
  244. return Dependence(D).nestedNameSpecifier();
  245. }
  246. inline TemplateArgumentDependence
  247. toTemplateArgumentDependence(TypeDependence D) {
  248. return Dependence(D).templateArgument();
  249. }
  250. inline TemplateArgumentDependence
  251. toTemplateArgumentDependence(TemplateNameDependence D) {
  252. return Dependence(D).templateArgument();
  253. }
  254. inline TemplateArgumentDependence
  255. toTemplateArgumentDependence(ExprDependence D) {
  256. return Dependence(D).templateArgument();
  257. }
  258. inline TemplateNameDependence
  259. toTemplateNameDependence(NestedNameSpecifierDependence D) {
  260. return Dependence(D).templateName();
  261. }
  262. LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
  263. } // namespace clang
  264. #endif
  265. #ifdef __GNUC__
  266. #pragma GCC diagnostic pop
  267. #endif