Viewing file: DependenceFlags.h (12.45 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===--- 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, ErrorDependent = Error | ValueInstantiation,
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,
// Dependence that is propagated syntactically, regardless of semantics. Syntactic = UnexpandedPack | Instantiation | Error, // Dependence that is propagated semantically, even in cases where the // type doesn't syntactically appear. This currently excludes only // UnexpandedPack. Even though Instantiation dependence is also notionally // syntactic, we also want to propagate it semantically because anything // that semantically depends on an instantiation-dependent entity should // always be instantiated when that instantiation-dependent entity is. Semantic = Instantiation | Type | Value | Dependent | Error | VariablyModified,
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)) {}
/// Extract only the syntactic portions of this type's dependence. Dependence syntactic() { Dependence Result = *this; Result.V &= Syntactic; return Result; }
/// Extract the semantic portions of this type's dependence that apply even /// to uses where the type does not appear syntactically. Dependence semantic() { Dependence Result = *this; Result.V &= Semantic; return Result; }
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 toExprDependenceForImpliedType(TypeDependence D) { return Dependence(D).semantic().expr(); } inline ExprDependence toExprDependenceAsWritten(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 TypeDependence toSyntacticDependence(TypeDependence D) { return Dependence(D).syntactic().type(); } inline TypeDependence toSemanticDependence(TypeDependence D) { return Dependence(D).semantic().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
|