Home | History | Annotate | Line # | Download | only in AST
      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