summaryrefslogtreecommitdiff
path: root/clang/include/clang/AST/DependenceFlags.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include/clang/AST/DependenceFlags.h')
-rw-r--r--clang/include/clang/AST/DependenceFlags.h284
1 files changed, 284 insertions, 0 deletions
diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h
new file mode 100644
index 0000000000000..14a7ffaecb2b0
--- /dev/null
+++ b/clang/include/clang/AST/DependenceFlags.h
@@ -0,0 +1,284 @@
+//===--- DependenceFlags.h ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DEPENDENCEFLAGS_H
+#define LLVM_CLANG_AST_DEPENDENCEFLAGS_H
+
+#include "clang/Basic/BitmaskEnum.h"
+#include "llvm/ADT/BitmaskEnum.h"
+#include <cstdint>
+
+namespace clang {
+struct ExprDependenceScope {
+ enum ExprDependence : uint8_t {
+ UnexpandedPack = 1,
+ // This expr depends in any way on
+ // - a template parameter, it implies that the resolution of this expr may
+ // cause instantiation to fail
+ // - or an error (often in a non-template context)
+ //
+ // Note that C++ standard doesn't define the instantiation-dependent term,
+ // we follow the formal definition coming from the Itanium C++ ABI, and
+ // extend it to errors.
+ Instantiation = 2,
+ // The type of this expr depends on a template parameter, or an error.
+ Type = 4,
+ // The value of this expr depends on a template parameter, or an error.
+ Value = 8,
+
+ // clang extension: this expr contains or references an error, and is
+ // considered dependent on how that error is resolved.
+ Error = 16,
+
+ None = 0,
+ All = 31,
+
+ TypeValue = Type | Value,
+ TypeInstantiation = Type | Instantiation,
+ ValueInstantiation = Value | Instantiation,
+ TypeValueInstantiation = Type | Value | Instantiation,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
+ };
+};
+using ExprDependence = ExprDependenceScope::ExprDependence;
+
+struct TypeDependenceScope {
+ enum TypeDependence : uint8_t {
+ /// Whether this type contains an unexpanded parameter pack
+ /// (for C++11 variadic templates)
+ UnexpandedPack = 1,
+ /// Whether this type somehow involves
+ /// - a template parameter, even if the resolution of the type does not
+ /// depend on a template parameter.
+ /// - or an error.
+ Instantiation = 2,
+ /// Whether this type
+ /// - is a dependent type (C++ [temp.dep.type])
+ /// - or it somehow involves an error, e.g. decltype(recovery-expr)
+ Dependent = 4,
+ /// Whether this type is a variably-modified type (C99 6.7.5).
+ VariablyModified = 8,
+
+ /// Whether this type references an error, e.g. decltype(err-expression)
+ /// yields an error type.
+ Error = 16,
+
+ None = 0,
+ All = 31,
+
+ DependentInstantiation = Dependent | Instantiation,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error)
+ };
+};
+using TypeDependence = TypeDependenceScope::TypeDependence;
+
+#define LLVM_COMMON_DEPENDENCE(NAME) \
+ struct NAME##Scope { \
+ enum NAME : uint8_t { \
+ UnexpandedPack = 1, \
+ Instantiation = 2, \
+ Dependent = 4, \
+ Error = 8, \
+ \
+ None = 0, \
+ DependentInstantiation = Dependent | Instantiation, \
+ All = 15, \
+ \
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) \
+ }; \
+ }; \
+ using NAME = NAME##Scope::NAME;
+
+LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence)
+LLVM_COMMON_DEPENDENCE(TemplateNameDependence)
+LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence)
+#undef LLVM_COMMON_DEPENDENCE
+
+// A combined space of all dependence concepts for all node types.
+// Used when aggregating dependence of nodes of different types.
+class Dependence {
+public:
+ enum Bits : uint8_t {
+ None = 0,
+
+ // Contains a template parameter pack that wasn't expanded.
+ UnexpandedPack = 1,
+ // Depends on a template parameter or an error in some way.
+ // Validity depends on how the template is instantiated or the error is
+ // resolved.
+ Instantiation = 2,
+ // Expression type depends on template context, or an error.
+ // Value and Instantiation should also be set.
+ Type = 4,
+ // Expression value depends on template context, or an error.
+ // Instantiation should also be set.
+ Value = 8,
+ // Depends on template context, or an error.
+ // The type/value distinction is only meaningful for expressions.
+ Dependent = Type | Value,
+ // Includes an error, and depends on how it is resolved.
+ Error = 16,
+ // Type depends on a runtime value (variable-length array).
+ VariablyModified = 32,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
+ };
+
+ Dependence() : V(None) {}
+
+ Dependence(TypeDependence D)
+ : V(translate(D, TypeDependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, TypeDependence::Instantiation, Instantiation) |
+ translate(D, TypeDependence::Dependent, Dependent) |
+ translate(D, TypeDependence::Error, Error) |
+ translate(D, TypeDependence::VariablyModified, VariablyModified)) {}
+
+ Dependence(ExprDependence D)
+ : V(translate(D, ExprDependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, ExprDependence::Instantiation, Instantiation) |
+ translate(D, ExprDependence::Type, Type) |
+ translate(D, ExprDependence::Value, Value) |
+ translate(D, ExprDependence::Error, Error)) {}
+
+ Dependence(NestedNameSpecifierDependence D) :
+ V ( translate(D, NNSDependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, NNSDependence::Instantiation, Instantiation) |
+ translate(D, NNSDependence::Dependent, Dependent) |
+ translate(D, NNSDependence::Error, Error)) {}
+
+ Dependence(TemplateArgumentDependence D)
+ : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, TADependence::Instantiation, Instantiation) |
+ translate(D, TADependence::Dependent, Dependent) |
+ translate(D, TADependence::Error, Error)) {}
+
+ Dependence(TemplateNameDependence D)
+ : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) |
+ translate(D, TNDependence::Instantiation, Instantiation) |
+ translate(D, TNDependence::Dependent, Dependent) |
+ translate(D, TNDependence::Error, Error)) {}
+
+ TypeDependence type() const {
+ return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
+ translate(V, Instantiation, TypeDependence::Instantiation) |
+ translate(V, Dependent, TypeDependence::Dependent) |
+ translate(V, Error, TypeDependence::Error) |
+ translate(V, VariablyModified, TypeDependence::VariablyModified);
+ }
+
+ ExprDependence expr() const {
+ return translate(V, UnexpandedPack, ExprDependence::UnexpandedPack) |
+ translate(V, Instantiation, ExprDependence::Instantiation) |
+ translate(V, Type, ExprDependence::Type) |
+ translate(V, Value, ExprDependence::Value) |
+ translate(V, Error, ExprDependence::Error);
+ }
+
+ NestedNameSpecifierDependence nestedNameSpecifier() const {
+ return translate(V, UnexpandedPack, NNSDependence::UnexpandedPack) |
+ translate(V, Instantiation, NNSDependence::Instantiation) |
+ translate(V, Dependent, NNSDependence::Dependent) |
+ translate(V, Error, NNSDependence::Error);
+ }
+
+ TemplateArgumentDependence templateArgument() const {
+ return translate(V, UnexpandedPack, TADependence::UnexpandedPack) |
+ translate(V, Instantiation, TADependence::Instantiation) |
+ translate(V, Dependent, TADependence::Dependent) |
+ translate(V, Error, TADependence::Error);
+ }
+
+ TemplateNameDependence templateName() const {
+ return translate(V, UnexpandedPack, TNDependence::UnexpandedPack) |
+ translate(V, Instantiation, TNDependence::Instantiation) |
+ translate(V, Dependent, TNDependence::Dependent) |
+ translate(V, Error, TNDependence::Error);
+ }
+
+private:
+ Bits V;
+
+ template <typename T, typename U>
+ static U translate(T Bits, T FromBit, U ToBit) {
+ return (Bits & FromBit) ? ToBit : static_cast<U>(0);
+ }
+
+ // Abbreviations to make conversions more readable.
+ using NNSDependence = NestedNameSpecifierDependence;
+ using TADependence = TemplateArgumentDependence;
+ using TNDependence = TemplateNameDependence;
+};
+
+/// Computes dependencies of a reference with the name having template arguments
+/// with \p TA dependencies.
+inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
+ return Dependence(TA).expr();
+}
+inline ExprDependence toExprDependence(TypeDependence D) {
+ return Dependence(D).expr();
+}
+// Note: it's often necessary to strip `Dependent` from qualifiers.
+// If V<T>:: refers to the current instantiation, NNS is considered dependent
+// but the containing V<T>::foo likely isn't.
+inline ExprDependence toExprDependence(NestedNameSpecifierDependence D) {
+ return Dependence(D).expr();
+}
+inline ExprDependence turnTypeToValueDependence(ExprDependence D) {
+ // Type-dependent expressions are always be value-dependent, so we simply drop
+ // type dependency.
+ return D & ~ExprDependence::Type;
+}
+inline ExprDependence turnValueToTypeDependence(ExprDependence D) {
+ // Type-dependent expressions are always be value-dependent.
+ if (D & ExprDependence::Value)
+ D |= ExprDependence::Type;
+ return D;
+}
+
+// Returned type-dependence will never have VariablyModified set.
+inline TypeDependence toTypeDependence(ExprDependence D) {
+ return Dependence(D).type();
+}
+inline TypeDependence toTypeDependence(NestedNameSpecifierDependence D) {
+ return Dependence(D).type();
+}
+inline TypeDependence toTypeDependence(TemplateNameDependence D) {
+ return Dependence(D).type();
+}
+inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
+ return Dependence(D).type();
+}
+
+inline NestedNameSpecifierDependence
+toNestedNameSpecifierDependendence(TypeDependence D) {
+ return Dependence(D).nestedNameSpecifier();
+}
+
+inline TemplateArgumentDependence
+toTemplateArgumentDependence(TypeDependence D) {
+ return Dependence(D).templateArgument();
+}
+inline TemplateArgumentDependence
+toTemplateArgumentDependence(TemplateNameDependence D) {
+ return Dependence(D).templateArgument();
+}
+inline TemplateArgumentDependence
+toTemplateArgumentDependence(ExprDependence D) {
+ return Dependence(D).templateArgument();
+}
+
+inline TemplateNameDependence
+toTemplateNameDependence(NestedNameSpecifierDependence D) {
+ return Dependence(D).templateName();
+}
+
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+} // namespace clang
+#endif