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