clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
322 lines
12 KiB
C++
322 lines
12 KiB
C++
//===--- 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
|