//===- ComputeDependence.cpp ----------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "llvm/ADT/ArrayRef.h"

using namespace clang;

ExprDependence clang::computeDependence(FullExpr *E) {
  return E->getSubExpr()->getDependence();
}

ExprDependence clang::computeDependence(OpaqueValueExpr *E) {
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
  if (auto *S = E->getSourceExpr())
    D |= S->getDependence();
  assert(!(D & ExprDependence::UnexpandedPack));
  return D;
}

ExprDependence clang::computeDependence(ParenExpr *E) {
  return E->getSubExpr()->getDependence();
}

ExprDependence clang::computeDependence(UnaryOperator *E,
                                        const ASTContext &Ctx) {
  ExprDependence Dep =
      // FIXME: Do we need to look at the type?
      toExprDependenceForImpliedType(E->getType()->getDependence()) |
      E->getSubExpr()->getDependence();

  // C++ [temp.dep.constexpr]p5:
  //   An expression of the form & qualified-id where the qualified-id names a
  //   dependent member of the current instantiation is value-dependent. An
  //   expression of the form & cast-expression is also value-dependent if
  //   evaluating cast-expression as a core constant expression succeeds and
  //   the result of the evaluation refers to a templated entity that is an
  //   object with static or thread storage duration or a member function.
  //
  // What this amounts to is: constant-evaluate the operand and check whether it
  // refers to a templated entity other than a variable with local storage.
  if (Ctx.getLangOpts().CPlusPlus && E->getOpcode() == UO_AddrOf &&
      !(Dep & ExprDependence::Value)) {
    Expr::EvalResult Result;
    SmallVector<PartialDiagnosticAt, 8> Diag;
    Result.Diag = &Diag;
    // FIXME: This doesn't enforce the C++98 constant expression rules.
    if (E->getSubExpr()->EvaluateAsConstantExpr(Result, Ctx) && Diag.empty() &&
        Result.Val.isLValue()) {
      auto *VD = Result.Val.getLValueBase().dyn_cast<const ValueDecl *>();
      if (VD && VD->isTemplated()) {
        auto *VarD = dyn_cast<VarDecl>(VD);
        if (!VarD || !VarD->hasLocalStorage())
          Dep |= ExprDependence::Value;
      }
    }
  }

  return Dep;
}

ExprDependence clang::computeDependence(UnaryExprOrTypeTraitExpr *E) {
  // Never type-dependent (C++ [temp.dep.expr]p3).
  // Value-dependent if the argument is type-dependent.
  if (E->isArgumentType())
    return turnTypeToValueDependence(
        toExprDependenceAsWritten(E->getArgumentType()->getDependence()));

  auto ArgDeps = E->getArgumentExpr()->getDependence();
  auto Deps = ArgDeps & ~ExprDependence::TypeValue;
  // Value-dependent if the argument is type-dependent.
  if (ArgDeps & ExprDependence::Type)
    Deps |= ExprDependence::Value;
  // Check to see if we are in the situation where alignof(decl) should be
  // dependent because decl's alignment is dependent.
  auto ExprKind = E->getKind();
  if (ExprKind != UETT_AlignOf && ExprKind != UETT_PreferredAlignOf)
    return Deps;
  if ((Deps & ExprDependence::Value) && (Deps & ExprDependence::Instantiation))
    return Deps;

  auto *NoParens = E->getArgumentExpr()->IgnoreParens();
  const ValueDecl *D = nullptr;
  if (const auto *DRE = dyn_cast<DeclRefExpr>(NoParens))
    D = DRE->getDecl();
  else if (const auto *ME = dyn_cast<MemberExpr>(NoParens))
    D = ME->getMemberDecl();
  if (!D)
    return Deps;
  for (const auto *I : D->specific_attrs<AlignedAttr>()) {
    if (I->isAlignmentErrorDependent())
      Deps |= ExprDependence::Error;
    if (I->isAlignmentDependent())
      Deps |= ExprDependence::ValueInstantiation;
  }
  return Deps;
}

ExprDependence clang::computeDependence(ArraySubscriptExpr *E) {
  return E->getLHS()->getDependence() | E->getRHS()->getDependence();
}

ExprDependence clang::computeDependence(MatrixSubscriptExpr *E) {
  return E->getBase()->getDependence() | E->getRowIdx()->getDependence() |
         (E->getColumnIdx() ? E->getColumnIdx()->getDependence()
                            : ExprDependence::None);
}

ExprDependence clang::computeDependence(CompoundLiteralExpr *E) {
  return toExprDependenceAsWritten(
             E->getTypeSourceInfo()->getType()->getDependence()) |
         toExprDependenceForImpliedType(E->getType()->getDependence()) |
         turnTypeToValueDependence(E->getInitializer()->getDependence());
}

ExprDependence clang::computeDependence(ImplicitCastExpr *E) {
  // We model implicit conversions as combining the dependence of their
  // subexpression, apart from its type, with the semantic portion of the
  // target type.
  ExprDependence D =
      toExprDependenceForImpliedType(E->getType()->getDependence());
  if (auto *S = E->getSubExpr())
    D |= S->getDependence() & ~ExprDependence::Type;
  return D;
}

ExprDependence clang::computeDependence(ExplicitCastExpr *E) {
  // Cast expressions are type-dependent if the type is
  // dependent (C++ [temp.dep.expr]p3).
  // Cast expressions are value-dependent if the type is
  // dependent or if the subexpression is value-dependent.
  //
  // Note that we also need to consider the dependence of the actual type here,
  // because when the type as written is a deduced type, that type is not
  // dependent, but it may be deduced as a dependent type.
  ExprDependence D =
      toExprDependenceAsWritten(
          cast<ExplicitCastExpr>(E)->getTypeAsWritten()->getDependence()) |
      toExprDependenceForImpliedType(E->getType()->getDependence());
  if (auto *S = E->getSubExpr())
    D |= S->getDependence() & ~ExprDependence::Type;
  return D;
}

ExprDependence clang::computeDependence(BinaryOperator *E) {
  return E->getLHS()->getDependence() | E->getRHS()->getDependence();
}

ExprDependence clang::computeDependence(ConditionalOperator *E) {
  // The type of the conditional operator depends on the type of the conditional
  // to support the GCC vector conditional extension. Additionally,
  // [temp.dep.expr] does specify state that this should be dependent on ALL sub
  // expressions.
  return E->getCond()->getDependence() | E->getLHS()->getDependence() |
         E->getRHS()->getDependence();
}

ExprDependence clang::computeDependence(BinaryConditionalOperator *E) {
  return E->getCommon()->getDependence() | E->getFalseExpr()->getDependence();
}

ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
  // Propagate dependence of the result.
  if (const auto *CompoundExprResult =
          dyn_cast_or_null<ValueStmt>(E->getSubStmt()->getStmtExprResult()))
    if (const Expr *ResultExpr = CompoundExprResult->getExprStmt())
      D |= ResultExpr->getDependence();
  // Note: we treat a statement-expression in a dependent context as always
  // being value- and instantiation-dependent. This matches the behavior of
  // lambda-expressions and GCC.
  if (TemplateDepth)
    D |= ExprDependence::ValueInstantiation;
  // A param pack cannot be expanded over stmtexpr boundaries.
  return D & ~ExprDependence::UnexpandedPack;
}

ExprDependence clang::computeDependence(ConvertVectorExpr *E) {
  auto D = toExprDependenceAsWritten(
               E->getTypeSourceInfo()->getType()->getDependence()) |
           E->getSrcExpr()->getDependence();
  if (!E->getType()->isDependentType())
    D &= ~ExprDependence::Type;
  return D;
}

ExprDependence clang::computeDependence(ChooseExpr *E) {
  if (E->isConditionDependent())
    return ExprDependence::TypeValueInstantiation |
           E->getCond()->getDependence() | E->getLHS()->getDependence() |
           E->getRHS()->getDependence();

  auto Cond = E->getCond()->getDependence();
  auto Active = E->getLHS()->getDependence();
  auto Inactive = E->getRHS()->getDependence();
  if (!E->isConditionTrue())
    std::swap(Active, Inactive);
  // Take type- and value- dependency from the active branch. Propagate all
  // other flags from all branches.
  return (Active & ExprDependence::TypeValue) |
         ((Cond | Active | Inactive) & ~ExprDependence::TypeValue);
}

ExprDependence clang::computeDependence(ParenListExpr *P) {
  auto D = ExprDependence::None;
  for (auto *E : P->exprs())
    D |= E->getDependence();
  return D;
}

ExprDependence clang::computeDependence(VAArgExpr *E) {
  auto D = toExprDependenceAsWritten(
               E->getWrittenTypeInfo()->getType()->getDependence()) |
           (E->getSubExpr()->getDependence() & ~ExprDependence::Type);
  return D & ~ExprDependence::Value;
}

ExprDependence clang::computeDependence(NoInitExpr *E) {
  return toExprDependenceForImpliedType(E->getType()->getDependence()) &
         (ExprDependence::Instantiation | ExprDependence::Error);
}

ExprDependence clang::computeDependence(ArrayInitLoopExpr *E) {
  auto D = E->getCommonExpr()->getDependence() |
           E->getSubExpr()->getDependence() | ExprDependence::Instantiation;
  if (!E->getType()->isInstantiationDependentType())
    D &= ~ExprDependence::Instantiation;
  return turnTypeToValueDependence(D);
}

ExprDependence clang::computeDependence(ImplicitValueInitExpr *E) {
  return toExprDependenceForImpliedType(E->getType()->getDependence()) &
         ExprDependence::Instantiation;
}

ExprDependence clang::computeDependence(ExtVectorElementExpr *E) {
  return E->getBase()->getDependence();
}

ExprDependence clang::computeDependence(BlockExpr *E) {
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
  if (E->getBlockDecl()->isDependentContext())
    D |= ExprDependence::Instantiation;
  return D;
}

ExprDependence clang::computeDependence(AsTypeExpr *E) {
  // FIXME: AsTypeExpr doesn't store the type as written. Assume the expression
  // type has identical sugar for now, so is a type-as-written.
  auto D = toExprDependenceAsWritten(E->getType()->getDependence()) |
           E->getSrcExpr()->getDependence();
  if (!E->getType()->isDependentType())
    D &= ~ExprDependence::Type;
  return D;
}

ExprDependence clang::computeDependence(CXXRewrittenBinaryOperator *E) {
  return E->getSemanticForm()->getDependence();
}

ExprDependence clang::computeDependence(CXXStdInitializerListExpr *E) {
  auto D = turnTypeToValueDependence(E->getSubExpr()->getDependence());
  D |= toExprDependenceForImpliedType(E->getType()->getDependence());
  return D;
}

ExprDependence clang::computeDependence(CXXTypeidExpr *E) {
  auto D = ExprDependence::None;
  if (E->isTypeOperand())
    D = toExprDependenceAsWritten(
        E->getTypeOperandSourceInfo()->getType()->getDependence());
  else
    D = turnTypeToValueDependence(E->getExprOperand()->getDependence());
  // typeid is never type-dependent (C++ [temp.dep.expr]p4)
  return D & ~ExprDependence::Type;
}

ExprDependence clang::computeDependence(MSPropertyRefExpr *E) {
  return E->getBaseExpr()->getDependence() & ~ExprDependence::Type;
}

ExprDependence clang::computeDependence(MSPropertySubscriptExpr *E) {
  return E->getIdx()->getDependence();
}

ExprDependence clang::computeDependence(CXXUuidofExpr *E) {
  if (E->isTypeOperand())
    return turnTypeToValueDependence(toExprDependenceAsWritten(
        E->getTypeOperandSourceInfo()->getType()->getDependence()));

  return turnTypeToValueDependence(E->getExprOperand()->getDependence());
}

ExprDependence clang::computeDependence(CXXThisExpr *E) {
  // 'this' is type-dependent if the class type of the enclosing
  // member function is dependent (C++ [temp.dep.expr]p2)
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
  assert(!(D & ExprDependence::UnexpandedPack));
  return D;
}

ExprDependence clang::computeDependence(CXXThrowExpr *E) {
  auto *Op = E->getSubExpr();
  if (!Op)
    return ExprDependence::None;
  return Op->getDependence() & ~ExprDependence::TypeValue;
}

ExprDependence clang::computeDependence(CXXBindTemporaryExpr *E) {
  return E->getSubExpr()->getDependence();
}

ExprDependence clang::computeDependence(CXXScalarValueInitExpr *E) {
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
  if (auto *TSI = E->getTypeSourceInfo())
    D |= toExprDependenceAsWritten(TSI->getType()->getDependence());
  return D;
}

ExprDependence clang::computeDependence(CXXDeleteExpr *E) {
  return turnTypeToValueDependence(E->getArgument()->getDependence());
}

ExprDependence clang::computeDependence(ArrayTypeTraitExpr *E) {
  auto D = toExprDependenceAsWritten(E->getQueriedType()->getDependence());
  if (auto *Dim = E->getDimensionExpression())
    D |= Dim->getDependence();
  return turnTypeToValueDependence(D);
}

ExprDependence clang::computeDependence(ExpressionTraitExpr *E) {
  // Never type-dependent.
  auto D = E->getQueriedExpression()->getDependence() & ~ExprDependence::Type;
  // Value-dependent if the argument is type-dependent.
  if (E->getQueriedExpression()->isTypeDependent())
    D |= ExprDependence::Value;
  return D;
}

ExprDependence clang::computeDependence(CXXNoexceptExpr *E, CanThrowResult CT) {
  auto D = E->getOperand()->getDependence() & ~ExprDependence::TypeValue;
  if (CT == CT_Dependent)
    D |= ExprDependence::ValueInstantiation;
  return D;
}

ExprDependence clang::computeDependence(PackExpansionExpr *E) {
  return (E->getPattern()->getDependence() & ~ExprDependence::UnexpandedPack) |
         ExprDependence::TypeValueInstantiation;
}

ExprDependence clang::computeDependence(SubstNonTypeTemplateParmExpr *E) {
  return E->getReplacement()->getDependence();
}

ExprDependence clang::computeDependence(CoroutineSuspendExpr *E) {
  if (auto *Resume = E->getResumeExpr())
    return (Resume->getDependence() &
            (ExprDependence::TypeValue | ExprDependence::Error)) |
           (E->getCommonExpr()->getDependence() & ~ExprDependence::TypeValue);
  return E->getCommonExpr()->getDependence() |
         ExprDependence::TypeValueInstantiation;
}

ExprDependence clang::computeDependence(DependentCoawaitExpr *E) {
  return E->getOperand()->getDependence() |
         ExprDependence::TypeValueInstantiation;
}

ExprDependence clang::computeDependence(ObjCBoxedExpr *E) {
  return E->getSubExpr()->getDependence();
}

ExprDependence clang::computeDependence(ObjCEncodeExpr *E) {
  return toExprDependenceAsWritten(E->getEncodedType()->getDependence());
}

ExprDependence clang::computeDependence(ObjCIvarRefExpr *E) {
  return turnTypeToValueDependence(E->getBase()->getDependence());
}

ExprDependence clang::computeDependence(ObjCPropertyRefExpr *E) {
  if (E->isObjectReceiver())
    return E->getBase()->getDependence() & ~ExprDependence::Type;
  if (E->isSuperReceiver())
    return toExprDependenceForImpliedType(
               E->getSuperReceiverType()->getDependence()) &
           ~ExprDependence::TypeValue;
  assert(E->isClassReceiver());
  return ExprDependence::None;
}

ExprDependence clang::computeDependence(ObjCSubscriptRefExpr *E) {
  return E->getBaseExpr()->getDependence() | E->getKeyExpr()->getDependence();
}

ExprDependence clang::computeDependence(ObjCIsaExpr *E) {
  return E->getBase()->getDependence() & ~ExprDependence::Type &
         ~ExprDependence::UnexpandedPack;
}

ExprDependence clang::computeDependence(ObjCIndirectCopyRestoreExpr *E) {
  return E->getSubExpr()->getDependence();
}

ExprDependence clang::computeDependence(OMPArraySectionExpr *E) {
  auto D = E->getBase()->getDependence();
  if (auto *LB = E->getLowerBound())
    D |= LB->getDependence();
  if (auto *Len = E->getLength())
    D |= Len->getDependence();
  return D;
}

ExprDependence clang::computeDependence(OMPArrayShapingExpr *E) {
  auto D = E->getBase()->getDependence();
  for (Expr *Dim: E->getDimensions())
    if (Dim)
      D |= turnValueToTypeDependence(Dim->getDependence());
  return D;
}

ExprDependence clang::computeDependence(OMPIteratorExpr *E) {
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
  for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
    if (auto *DD = cast_or_null<DeclaratorDecl>(E->getIteratorDecl(I))) {
      // If the type is omitted, it's 'int', and is not dependent in any way.
      if (auto *TSI = DD->getTypeSourceInfo()) {
        D |= toExprDependenceAsWritten(TSI->getType()->getDependence());
      }
    }
    OMPIteratorExpr::IteratorRange IR = E->getIteratorRange(I);
    if (Expr *BE = IR.Begin)
      D |= BE->getDependence();
    if (Expr *EE = IR.End)
      D |= EE->getDependence();
    if (Expr *SE = IR.Step)
      D |= SE->getDependence();
  }
  return D;
}

/// Compute the type-, value-, and instantiation-dependence of a
/// declaration reference
/// based on the declaration being referenced.
ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
  auto Deps = ExprDependence::None;

  if (auto *NNS = E->getQualifier())
    Deps |= toExprDependence(NNS->getDependence() &
                             ~NestedNameSpecifierDependence::Dependent);

  if (auto *FirstArg = E->getTemplateArgs()) {
    unsigned NumArgs = E->getNumTemplateArgs();
    for (auto *Arg = FirstArg, *End = FirstArg + NumArgs; Arg < End; ++Arg)
      Deps |= toExprDependence(Arg->getArgument().getDependence());
  }

  auto *Decl = E->getDecl();
  auto Type = E->getType();

  if (Decl->isParameterPack())
    Deps |= ExprDependence::UnexpandedPack;
  Deps |= toExprDependenceForImpliedType(Type->getDependence()) &
          ExprDependence::Error;

  // C++ [temp.dep.expr]p3:
  //   An id-expression is type-dependent if it contains:

  //    - an identifier associated by name lookup with one or more declarations
  //      declared with a dependent type
  //
  // [The "or more" case is not modeled as a DeclRefExpr. There are a bunch
  // more bullets here that we handle by treating the declaration as having a
  // dependent type if they involve a placeholder type that can't be deduced.]
  if (Type->isDependentType())
    return Deps | ExprDependence::TypeValueInstantiation;
  else if (Type->isInstantiationDependentType())
    Deps |= ExprDependence::Instantiation;

  //    - a conversion-function-id that specifies a dependent type
  if (Decl->getDeclName().getNameKind() ==
      DeclarationName::CXXConversionFunctionName) {
    QualType T = Decl->getDeclName().getCXXNameType();
    if (T->isDependentType())
      return Deps | ExprDependence::TypeValueInstantiation;

    if (T->isInstantiationDependentType())
      Deps |= ExprDependence::Instantiation;
  }

  //   - a template-id that is dependent,
  //   - a nested-name-specifier or a qualified-id that names a member of an
  //     unknown specialization
  //   [These are not modeled as DeclRefExprs.]

  //   or if it names a dependent member of the current instantiation that is a
  //   static data member of type "array of unknown bound of T" for some T
  //   [handled below].

  // C++ [temp.dep.constexpr]p2:
  //  An id-expression is value-dependent if:

  //    - it is type-dependent [handled above]

  //    - it is the name of a non-type template parameter,
  if (isa<NonTypeTemplateParmDecl>(Decl))
    return Deps | ExprDependence::ValueInstantiation;

  //   - it names a potentially-constant variable that is initialized with an
  //     expression that is value-dependent
  if (const auto *Var = dyn_cast<VarDecl>(Decl)) {
    if (Var->mightBeUsableInConstantExpressions(Ctx)) {
      if (const Expr *Init = Var->getAnyInitializer()) {
        if (Init->isValueDependent())
          Deps |= ExprDependence::ValueInstantiation;
        if (Init->containsErrors())
          Deps |= ExprDependence::Error;
      }
    }

    // - it names a static data member that is a dependent member of the
    //   current instantiation and is not initialized in a member-declarator,
    if (Var->isStaticDataMember() &&
        Var->getDeclContext()->isDependentContext() &&
        !Var->getFirstDecl()->hasInit()) {
      const VarDecl *First = Var->getFirstDecl();
      TypeSourceInfo *TInfo = First->getTypeSourceInfo();
      if (TInfo->getType()->isIncompleteArrayType()) {
        Deps |= ExprDependence::TypeValueInstantiation;
      } else if (!First->hasInit()) {
        Deps |= ExprDependence::ValueInstantiation;
      }
    }

    return Deps;
  }

  //   - it names a static member function that is a dependent member of the
  //     current instantiation
  //
  // FIXME: It's unclear that the restriction to static members here has any
  // effect: any use of a non-static member function name requires either
  // forming a pointer-to-member or providing an object parameter, either of
  // which makes the overall expression value-dependent.
  if (auto *MD = dyn_cast<CXXMethodDecl>(Decl)) {
    if (MD->isStatic() && Decl->getDeclContext()->isDependentContext())
      Deps |= ExprDependence::ValueInstantiation;
  }

  return Deps;
}

ExprDependence clang::computeDependence(RecoveryExpr *E) {
  // RecoveryExpr is
  //   - always value-dependent, and therefore instantiation dependent
  //   - contains errors (ExprDependence::Error), by definition
  //   - type-dependent if we don't know the type (fallback to an opaque
  //     dependent type), or the type is known and dependent, or it has
  //     type-dependent subexpressions.
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence()) |
           ExprDependence::ErrorDependent;
  // FIXME: remove the type-dependent bit from subexpressions, if the
  // RecoveryExpr has a non-dependent type.
  for (auto *S : E->subExpressions())
    D |= S->getDependence();
  return D;
}

ExprDependence clang::computeDependence(SYCLUniqueStableNameExpr *E) {
  return toExprDependenceAsWritten(
      E->getTypeSourceInfo()->getType()->getDependence());
}

ExprDependence clang::computeDependence(PredefinedExpr *E) {
  return toExprDependenceForImpliedType(E->getType()->getDependence());
}

ExprDependence clang::computeDependence(CallExpr *E,
                                        llvm::ArrayRef<Expr *> PreArgs) {
  auto D = E->getCallee()->getDependence();
  for (auto *A : llvm::makeArrayRef(E->getArgs(), E->getNumArgs())) {
    if (A)
      D |= A->getDependence();
  }
  for (auto *A : PreArgs)
    D |= A->getDependence();
  return D;
}

ExprDependence clang::computeDependence(OffsetOfExpr *E) {
  auto D = turnTypeToValueDependence(toExprDependenceAsWritten(
      E->getTypeSourceInfo()->getType()->getDependence()));
  for (unsigned I = 0, N = E->getNumExpressions(); I < N; ++I)
    D |= turnTypeToValueDependence(E->getIndexExpr(I)->getDependence());
  return D;
}

ExprDependence clang::computeDependence(MemberExpr *E) {
  auto *MemberDecl = E->getMemberDecl();
  auto D = E->getBase()->getDependence();
  if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
    DeclContext *DC = MemberDecl->getDeclContext();
    // dyn_cast_or_null is used to handle objC variables which do not
    // have a declaration context.
    CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC);
    if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC)) {
      if (!E->getType()->isDependentType())
        D &= ~ExprDependence::Type;
    }

    // Bitfield with value-dependent width is type-dependent.
    if (FD && FD->isBitField() && FD->getBitWidth()->isValueDependent()) {
      D |= ExprDependence::Type;
    }
  }
  // FIXME: move remaining dependence computation from MemberExpr::Create()
  return D;
}

ExprDependence clang::computeDependence(InitListExpr *E) {
  auto D = ExprDependence::None;
  for (auto *A : E->inits())
    D |= A->getDependence();
  return D;
}

ExprDependence clang::computeDependence(ShuffleVectorExpr *E) {
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
  for (auto *C : llvm::makeArrayRef(E->getSubExprs(), E->getNumSubExprs()))
    D |= C->getDependence();
  return D;
}

ExprDependence clang::computeDependence(GenericSelectionExpr *E,
                                        bool ContainsUnexpandedPack) {
  auto D = ContainsUnexpandedPack ? ExprDependence::UnexpandedPack
                                  : ExprDependence::None;
  for (auto *AE : E->getAssocExprs())
    D |= AE->getDependence() & ExprDependence::Error;
  D |= E->getControllingExpr()->getDependence() & ExprDependence::Error;

  if (E->isResultDependent())
    return D | ExprDependence::TypeValueInstantiation;
  return D | (E->getResultExpr()->getDependence() &
              ~ExprDependence::UnexpandedPack);
}

ExprDependence clang::computeDependence(DesignatedInitExpr *E) {
  auto Deps = E->getInit()->getDependence();
  for (auto D : E->designators()) {
    auto DesignatorDeps = ExprDependence::None;
    if (D.isArrayDesignator())
      DesignatorDeps |= E->getArrayIndex(D)->getDependence();
    else if (D.isArrayRangeDesignator())
      DesignatorDeps |= E->getArrayRangeStart(D)->getDependence() |
                        E->getArrayRangeEnd(D)->getDependence();
    Deps |= DesignatorDeps;
    if (DesignatorDeps & ExprDependence::TypeValue)
      Deps |= ExprDependence::TypeValueInstantiation;
  }
  return Deps;
}

ExprDependence clang::computeDependence(PseudoObjectExpr *O) {
  auto D = O->getSyntacticForm()->getDependence();
  for (auto *E : O->semantics())
    D |= E->getDependence();
  return D;
}

ExprDependence clang::computeDependence(AtomicExpr *A) {
  auto D = ExprDependence::None;
  for (auto *E : llvm::makeArrayRef(A->getSubExprs(), A->getNumSubExprs()))
    D |= E->getDependence();
  return D;
}

ExprDependence clang::computeDependence(CXXNewExpr *E) {
  auto D = toExprDependenceAsWritten(
      E->getAllocatedTypeSourceInfo()->getType()->getDependence());
  D |= toExprDependenceForImpliedType(E->getAllocatedType()->getDependence());
  auto Size = E->getArraySize();
  if (Size && *Size)
    D |= turnTypeToValueDependence((*Size)->getDependence());
  if (auto *I = E->getInitializer())
    D |= turnTypeToValueDependence(I->getDependence());
  for (auto *A : E->placement_arguments())
    D |= turnTypeToValueDependence(A->getDependence());
  return D;
}

ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) {
  auto D = E->getBase()->getDependence();
  if (auto *TSI = E->getDestroyedTypeInfo())
    D |= toExprDependenceAsWritten(TSI->getType()->getDependence());
  if (auto *ST = E->getScopeTypeInfo())
    D |= turnTypeToValueDependence(
        toExprDependenceAsWritten(ST->getType()->getDependence()));
  if (auto *Q = E->getQualifier())
    D |= toExprDependence(Q->getDependence() &
                          ~NestedNameSpecifierDependence::Dependent);
  return D;
}

static inline ExprDependence getDependenceInExpr(DeclarationNameInfo Name) {
  auto D = ExprDependence::None;
  if (Name.isInstantiationDependent())
    D |= ExprDependence::Instantiation;
  if (Name.containsUnexpandedParameterPack())
    D |= ExprDependence::UnexpandedPack;
  return D;
}

ExprDependence
clang::computeDependence(OverloadExpr *E, bool KnownDependent,
                         bool KnownInstantiationDependent,
                         bool KnownContainsUnexpandedParameterPack) {
  auto Deps = ExprDependence::None;
  if (KnownDependent)
    Deps |= ExprDependence::TypeValue;
  if (KnownInstantiationDependent)
    Deps |= ExprDependence::Instantiation;
  if (KnownContainsUnexpandedParameterPack)
    Deps |= ExprDependence::UnexpandedPack;
  Deps |= getDependenceInExpr(E->getNameInfo());
  if (auto *Q = E->getQualifier())
    Deps |= toExprDependence(Q->getDependence() &
                             ~NestedNameSpecifierDependence::Dependent);
  for (auto *D : E->decls()) {
    if (D->getDeclContext()->isDependentContext() ||
        isa<UnresolvedUsingValueDecl>(D))
      Deps |= ExprDependence::TypeValueInstantiation;
  }
  // If we have explicit template arguments, check for dependent
  // template arguments and whether they contain any unexpanded pack
  // expansions.
  for (auto A : E->template_arguments())
    Deps |= toExprDependence(A.getArgument().getDependence());
  return Deps;
}

ExprDependence clang::computeDependence(DependentScopeDeclRefExpr *E) {
  auto D = ExprDependence::TypeValue;
  D |= getDependenceInExpr(E->getNameInfo());
  if (auto *Q = E->getQualifier())
    D |= toExprDependence(Q->getDependence());
  for (auto A : E->template_arguments())
    D |= toExprDependence(A.getArgument().getDependence());
  return D;
}

ExprDependence clang::computeDependence(CXXConstructExpr *E) {
  ExprDependence D =
      toExprDependenceForImpliedType(E->getType()->getDependence());
  for (auto *A : E->arguments())
    D |= A->getDependence() & ~ExprDependence::Type;
  return D;
}

ExprDependence clang::computeDependence(CXXTemporaryObjectExpr *E) {
  CXXConstructExpr *BaseE = E;
  return toExprDependenceAsWritten(
             E->getTypeSourceInfo()->getType()->getDependence()) |
         computeDependence(BaseE);
}

ExprDependence clang::computeDependence(CXXDefaultInitExpr *E) {
  return E->getExpr()->getDependence();
}

ExprDependence clang::computeDependence(CXXDefaultArgExpr *E) {
  return E->getExpr()->getDependence();
}

ExprDependence clang::computeDependence(LambdaExpr *E,
                                        bool ContainsUnexpandedParameterPack) {
  auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
  if (ContainsUnexpandedParameterPack)
    D |= ExprDependence::UnexpandedPack;
  return D;
}

ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) {
  auto D = ExprDependence::ValueInstantiation;
  D |= toExprDependenceAsWritten(E->getTypeAsWritten()->getDependence());
  D |= toExprDependenceForImpliedType(E->getType()->getDependence());
  for (auto *A : E->arguments())
    D |= A->getDependence() &
         (ExprDependence::UnexpandedPack | ExprDependence::Error);
  return D;
}

ExprDependence clang::computeDependence(CXXDependentScopeMemberExpr *E) {
  auto D = ExprDependence::TypeValueInstantiation;
  if (!E->isImplicitAccess())
    D |= E->getBase()->getDependence();
  if (auto *Q = E->getQualifier())
    D |= toExprDependence(Q->getDependence());
  D |= getDependenceInExpr(E->getMemberNameInfo());
  for (auto A : E->template_arguments())
    D |= toExprDependence(A.getArgument().getDependence());
  return D;
}

ExprDependence clang::computeDependence(MaterializeTemporaryExpr *E) {
  return E->getSubExpr()->getDependence();
}

ExprDependence clang::computeDependence(CXXFoldExpr *E) {
  auto D = ExprDependence::TypeValueInstantiation;
  for (const auto *C : {E->getLHS(), E->getRHS()}) {
    if (C)
      D |= C->getDependence() & ~ExprDependence::UnexpandedPack;
  }
  return D;
}

ExprDependence clang::computeDependence(TypeTraitExpr *E) {
  auto D = ExprDependence::None;
  for (const auto *A : E->getArgs())
    D |= toExprDependenceAsWritten(A->getType()->getDependence()) &
         ~ExprDependence::Type;
  return D;
}

ExprDependence clang::computeDependence(ConceptSpecializationExpr *E,
                                        bool ValueDependent) {
  auto TA = TemplateArgumentDependence::None;
  const auto InterestingDeps = TemplateArgumentDependence::Instantiation |
                               TemplateArgumentDependence::UnexpandedPack;
  for (const TemplateArgumentLoc &ArgLoc :
       E->getTemplateArgsAsWritten()->arguments()) {
    TA |= ArgLoc.getArgument().getDependence() & InterestingDeps;
    if (TA == InterestingDeps)
      break;
  }

  ExprDependence D =
      ValueDependent ? ExprDependence::Value : ExprDependence::None;
  return D | toExprDependence(TA);
}

ExprDependence clang::computeDependence(ObjCArrayLiteral *E) {
  auto D = ExprDependence::None;
  Expr **Elements = E->getElements();
  for (unsigned I = 0, N = E->getNumElements(); I != N; ++I)
    D |= turnTypeToValueDependence(Elements[I]->getDependence());
  return D;
}

ExprDependence clang::computeDependence(ObjCDictionaryLiteral *E) {
  auto Deps = ExprDependence::None;
  for (unsigned I = 0, N = E->getNumElements(); I < N; ++I) {
    auto KV = E->getKeyValueElement(I);
    auto KVDeps = turnTypeToValueDependence(KV.Key->getDependence() |
                                            KV.Value->getDependence());
    if (KV.EllipsisLoc.isValid())
      KVDeps &= ~ExprDependence::UnexpandedPack;
    Deps |= KVDeps;
  }
  return Deps;
}

ExprDependence clang::computeDependence(ObjCMessageExpr *E) {
  auto D = ExprDependence::None;
  if (auto *R = E->getInstanceReceiver())
    D |= R->getDependence();
  else
    D |= toExprDependenceForImpliedType(E->getType()->getDependence());
  for (auto *A : E->arguments())
    D |= A->getDependence();
  return D;
}
