diff options
Diffstat (limited to 'clang/include/clang/AST/DependenceFlags.h')
-rw-r--r-- | clang/include/clang/AST/DependenceFlags.h | 284 |
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 |