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