//===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis member access expressions.
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/Overload.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"

using namespace clang;
using namespace sema;

typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet;

/// Determines if the given class is provably not derived from all of
/// the prospective base classes.
static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record,
                                     const BaseSet &Bases) {
  auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) {
    return !Bases.count(Base->getCanonicalDecl());
  };
  return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet);
}

enum IMAKind {
  /// The reference is definitely not an instance member access.
  IMA_Static,

  /// The reference may be an implicit instance member access.
  IMA_Mixed,

  /// The reference may be to an instance member, but it might be invalid if
  /// so, because the context is not an instance method.
  IMA_Mixed_StaticContext,

  /// The reference may be to an instance member, but it is invalid if
  /// so, because the context is from an unrelated class.
  IMA_Mixed_Unrelated,

  /// The reference is definitely an implicit instance member access.
  IMA_Instance,

  /// The reference may be to an unresolved using declaration.
  IMA_Unresolved,

  /// The reference is a contextually-permitted abstract member reference.
  IMA_Abstract,

  /// The reference may be to an unresolved using declaration and the
  /// context is not an instance method.
  IMA_Unresolved_StaticContext,

  // The reference refers to a field which is not a member of the containing
  // class, which is allowed because we're in C++11 mode and the context is
  // unevaluated.
  IMA_Field_Uneval_Context,

  /// All possible referrents are instance members and the current
  /// context is not an instance method.
  IMA_Error_StaticContext,

  /// All possible referrents are instance members of an unrelated
  /// class.
  IMA_Error_Unrelated
};

/// The given lookup names class member(s) and is not being used for
/// an address-of-member expression.  Classify the type of access
/// according to whether it's possible that this reference names an
/// instance member.  This is best-effort in dependent contexts; it is okay to
/// conservatively answer "yes", in which case some errors will simply
/// not be caught until template-instantiation.
static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
                                            const LookupResult &R) {
  assert(!R.empty() && (*R.begin())->isCXXClassMember());

  DeclContext *DC = SemaRef.getFunctionLevelDeclContext();

  bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() &&
    (!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic());

  if (R.isUnresolvableResult())
    return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;

  // Collect all the declaring classes of instance members we find.
  bool hasNonInstance = false;
  bool isField = false;
  BaseSet Classes;
  for (NamedDecl *D : R) {
    // Look through any using decls.
    D = D->getUnderlyingDecl();

    if (D->isCXXInstanceMember()) {
      isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) ||
                 isa<IndirectFieldDecl>(D);

      CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
      Classes.insert(R->getCanonicalDecl());
    } else
      hasNonInstance = true;
  }

  // If we didn't find any instance members, it can't be an implicit
  // member reference.
  if (Classes.empty())
    return IMA_Static;

  // C++11 [expr.prim.general]p12:
  //   An id-expression that denotes a non-static data member or non-static
  //   member function of a class can only be used:
  //   (...)
  //   - if that id-expression denotes a non-static data member and it
  //     appears in an unevaluated operand.
  //
  // This rule is specific to C++11.  However, we also permit this form
  // in unevaluated inline assembly operands, like the operand to a SIZE.
  IMAKind AbstractInstanceResult = IMA_Static; // happens to be 'false'
  assert(!AbstractInstanceResult);
  switch (SemaRef.ExprEvalContexts.back().Context) {
  case Sema::ExpressionEvaluationContext::Unevaluated:
  case Sema::ExpressionEvaluationContext::UnevaluatedList:
    if (isField && SemaRef.getLangOpts().CPlusPlus11)
      AbstractInstanceResult = IMA_Field_Uneval_Context;
    break;

  case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
    AbstractInstanceResult = IMA_Abstract;
    break;

  case Sema::ExpressionEvaluationContext::DiscardedStatement:
  case Sema::ExpressionEvaluationContext::ConstantEvaluated:
  case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
  case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
    break;
  }

  // If the current context is not an instance method, it can't be
  // an implicit member reference.
  if (isStaticContext) {
    if (hasNonInstance)
      return IMA_Mixed_StaticContext;

    return AbstractInstanceResult ? AbstractInstanceResult
                                  : IMA_Error_StaticContext;
  }

  CXXRecordDecl *contextClass;
  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
    contextClass = MD->getParent()->getCanonicalDecl();
  else
    contextClass = cast<CXXRecordDecl>(DC);

  // [class.mfct.non-static]p3:
  // ...is used in the body of a non-static member function of class X,
  // if name lookup (3.4.1) resolves the name in the id-expression to a
  // non-static non-type member of some class C [...]
  // ...if C is not X or a base class of X, the class member access expression
  // is ill-formed.
  if (R.getNamingClass() &&
      contextClass->getCanonicalDecl() !=
        R.getNamingClass()->getCanonicalDecl()) {
    // If the naming class is not the current context, this was a qualified
    // member name lookup, and it's sufficient to check that we have the naming
    // class as a base class.
    Classes.clear();
    Classes.insert(R.getNamingClass()->getCanonicalDecl());
  }

  // If we can prove that the current context is unrelated to all the
  // declaring classes, it can't be an implicit member reference (in
  // which case it's an error if any of those members are selected).
  if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes))
    return hasNonInstance ? IMA_Mixed_Unrelated :
           AbstractInstanceResult ? AbstractInstanceResult :
                                    IMA_Error_Unrelated;

  return (hasNonInstance ? IMA_Mixed : IMA_Instance);
}

/// Diagnose a reference to a field with no object available.
static void diagnoseInstanceReference(Sema &SemaRef,
                                      const CXXScopeSpec &SS,
                                      NamedDecl *Rep,
                                      const DeclarationNameInfo &nameInfo) {
  SourceLocation Loc = nameInfo.getLoc();
  SourceRange Range(Loc);
  if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());

  // Look through using shadow decls and aliases.
  Rep = Rep->getUnderlyingDecl();

  DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);
  CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;
  CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());

  bool InStaticMethod = Method && Method->isStatic();
  bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep);

  if (IsField && InStaticMethod)
    // "invalid use of member 'x' in static member function"
    SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
        << Range << nameInfo.getName();
  else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod &&
           !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass))
    // Unqualified lookup in a non-static member function found a member of an
    // enclosing class.
    SemaRef.Diag(Loc, diag::err_nested_non_static_member_use)
      << IsField << RepClass << nameInfo.getName() << ContextClass << Range;
  else if (IsField)
    SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
      << nameInfo.getName() << Range;
  else
    SemaRef.Diag(Loc, diag::err_member_call_without_object)
      << Range;
}

/// Builds an expression which might be an implicit member expression.
ExprResult Sema::BuildPossibleImplicitMemberExpr(
    const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
    const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
    UnresolvedLookupExpr *AsULE) {
  switch (ClassifyImplicitMemberAccess(*this, R)) {
  case IMA_Instance:
    return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);

  case IMA_Mixed:
  case IMA_Mixed_Unrelated:
  case IMA_Unresolved:
    return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
                                   S);

  case IMA_Field_Uneval_Context:
    Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
      << R.getLookupNameInfo().getName();
    LLVM_FALLTHROUGH;
  case IMA_Static:
  case IMA_Abstract:
  case IMA_Mixed_StaticContext:
  case IMA_Unresolved_StaticContext:
    if (TemplateArgs || TemplateKWLoc.isValid())
      return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
    return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);

  case IMA_Error_StaticContext:
  case IMA_Error_Unrelated:
    diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
                              R.getLookupNameInfo());
    return ExprError();
  }

  llvm_unreachable("unexpected instance member access kind");
}

/// Determine whether input char is from rgba component set.
static bool
IsRGBA(char c) {
  switch (c) {
  case 'r':
  case 'g':
  case 'b':
  case 'a':
    return true;
  default:
    return false;
  }
}

// OpenCL v1.1, s6.1.7
// The component swizzle length must be in accordance with the acceptable
// vector sizes.
static bool IsValidOpenCLComponentSwizzleLength(unsigned len)
{
  return (len >= 1 && len <= 4) || len == 8 || len == 16;
}

/// Check an ext-vector component access expression.
///
/// VK should be set in advance to the value kind of the base
/// expression.
static QualType
CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
                        SourceLocation OpLoc, const IdentifierInfo *CompName,
                        SourceLocation CompLoc) {
  // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,
  // see FIXME there.
  //
  // FIXME: This logic can be greatly simplified by splitting it along
  // halving/not halving and reworking the component checking.
  const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();

  // The vector accessor can't exceed the number of elements.
  const char *compStr = CompName->getNameStart();

  // This flag determines whether or not the component is one of the four
  // special names that indicate a subset of exactly half the elements are
  // to be selected.
  bool HalvingSwizzle = false;

  // This flag determines whether or not CompName has an 's' char prefix,
  // indicating that it is a string of hex values to be used as vector indices.
  bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1];

  bool HasRepeated = false;
  bool HasIndex[16] = {};

  int Idx;

  // Check that we've found one of the special components, or that the component
  // names must come from the same set.
  if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
      !strcmp(compStr, "even") || !strcmp(compStr, "odd")) {
    HalvingSwizzle = true;
  } else if (!HexSwizzle &&
             (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
    bool HasRGBA = IsRGBA(*compStr);
    do {
      // Ensure that xyzw and rgba components don't intermingle.
      if (HasRGBA != IsRGBA(*compStr))
        break;
      if (HasIndex[Idx]) HasRepeated = true;
      HasIndex[Idx] = true;
      compStr++;
    } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);

    // Emit a warning if an rgba selector is used earlier than OpenCL 2.2
    if (HasRGBA || (*compStr && IsRGBA(*compStr))) {
      if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion < 220) {
        const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr;
        S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector)
          << StringRef(DiagBegin, 1)
          << S.getLangOpts().OpenCLVersion << SourceRange(CompLoc);
      }
    }
  } else {
    if (HexSwizzle) compStr++;
    while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
      if (HasIndex[Idx]) HasRepeated = true;
      HasIndex[Idx] = true;
      compStr++;
    }
  }

  if (!HalvingSwizzle && *compStr) {
    // We didn't get to the end of the string. This means the component names
    // didn't come from the same set *or* we encountered an illegal name.
    S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
      << StringRef(compStr, 1) << SourceRange(CompLoc);
    return QualType();
  }

  // Ensure no component accessor exceeds the width of the vector type it
  // operates on.
  if (!HalvingSwizzle) {
    compStr = CompName->getNameStart();

    if (HexSwizzle)
      compStr++;

    while (*compStr) {
      if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) {
        S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
          << baseType << SourceRange(CompLoc);
        return QualType();
      }
    }
  }

  // OpenCL mode requires swizzle length to be in accordance with accepted
  // sizes. Clang however supports arbitrary lengths for other languages.
  if (S.getLangOpts().OpenCL && !HalvingSwizzle) {
    unsigned SwizzleLength = CompName->getLength();

    if (HexSwizzle)
      SwizzleLength--;

    if (IsValidOpenCLComponentSwizzleLength(SwizzleLength) == false) {
      S.Diag(OpLoc, diag::err_opencl_ext_vector_component_invalid_length)
        << SwizzleLength << SourceRange(CompLoc);
      return QualType();
    }
  }

  // The component accessor looks fine - now we need to compute the actual type.
  // The vector type is implied by the component accessor. For example,
  // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
  // vec4.s0 is a float, vec4.s23 is a vec3, etc.
  // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
  unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2
                                     : CompName->getLength();
  if (HexSwizzle)
    CompSize--;

  if (CompSize == 1)
    return vecType->getElementType();

  if (HasRepeated) VK = VK_RValue;

  QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);
  // Now look up the TypeDefDecl from the vector type. Without this,
  // diagostics look bad. We want extended vector types to appear built-in.
  for (Sema::ExtVectorDeclsType::iterator
         I = S.ExtVectorDecls.begin(S.getExternalSource()),
         E = S.ExtVectorDecls.end();
       I != E; ++I) {
    if ((*I)->getUnderlyingType() == VT)
      return S.Context.getTypedefType(*I);
  }

  return VT; // should never get here (a typedef type should always be found).
}

static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
                                                IdentifierInfo *Member,
                                                const Selector &Sel,
                                                ASTContext &Context) {
  if (Member)
    if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(
            Member, ObjCPropertyQueryKind::OBJC_PR_query_instance))
      return PD;
  if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
    return OMD;

  for (const auto *I : PDecl->protocols()) {
    if (Decl *D = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel,
                                                           Context))
      return D;
  }
  return nullptr;
}

static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
                                      IdentifierInfo *Member,
                                      const Selector &Sel,
                                      ASTContext &Context) {
  // Check protocols on qualified interfaces.
  Decl *GDecl = nullptr;
  for (const auto *I : QIdTy->quals()) {
    if (Member)
      if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(
              Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
        GDecl = PD;
        break;
      }
    // Also must look for a getter or setter name which uses property syntax.
    if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) {
      GDecl = OMD;
      break;
    }
  }
  if (!GDecl) {
    for (const auto *I : QIdTy->quals()) {
      // Search in the protocol-qualifier list of current protocol.
      GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context);
      if (GDecl)
        return GDecl;
    }
  }
  return GDecl;
}

ExprResult
Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
                               bool IsArrow, SourceLocation OpLoc,
                               const CXXScopeSpec &SS,
                               SourceLocation TemplateKWLoc,
                               NamedDecl *FirstQualifierInScope,
                               const DeclarationNameInfo &NameInfo,
                               const TemplateArgumentListInfo *TemplateArgs) {
  // Even in dependent contexts, try to diagnose base expressions with
  // obviously wrong types, e.g.:
  //
  // T* t;
  // t.f;
  //
  // In Obj-C++, however, the above expression is valid, since it could be
  // accessing the 'f' property if T is an Obj-C interface. The extra check
  // allows this, while still reporting an error if T is a struct pointer.
  if (!IsArrow) {
    const PointerType *PT = BaseType->getAs<PointerType>();
    if (PT && (!getLangOpts().ObjC ||
               PT->getPointeeType()->isRecordType())) {
      assert(BaseExpr && "cannot happen with implicit member accesses");
      Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
        << BaseType << BaseExpr->getSourceRange() << NameInfo.getSourceRange();
      return ExprError();
    }
  }

  assert(BaseType->isDependentType() ||
         NameInfo.getName().isDependentName() ||
         isDependentScopeSpecifier(SS));

  // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
  // must have pointer type, and the accessed type is the pointee.
  return CXXDependentScopeMemberExpr::Create(
      Context, BaseExpr, BaseType, IsArrow, OpLoc,
      SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope,
      NameInfo, TemplateArgs);
}

/// We know that the given qualified member reference points only to
/// declarations which do not belong to the static type of the base
/// expression.  Diagnose the problem.
static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
                                             Expr *BaseExpr,
                                             QualType BaseType,
                                             const CXXScopeSpec &SS,
                                             NamedDecl *rep,
                                       const DeclarationNameInfo &nameInfo) {
  // If this is an implicit member access, use a different set of
  // diagnostics.
  if (!BaseExpr)
    return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo);

  SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)
    << SS.getRange() << rep << BaseType;
}

// Check whether the declarations we found through a nested-name
// specifier in a member expression are actually members of the base
// type.  The restriction here is:
//
//   C++ [expr.ref]p2:
//     ... In these cases, the id-expression shall name a
//     member of the class or of one of its base classes.
//
// So it's perfectly legitimate for the nested-name specifier to name
// an unrelated class, and for us to find an overload set including
// decls from classes which are not superclasses, as long as the decl
// we actually pick through overload resolution is from a superclass.
bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
                                         QualType BaseType,
                                         const CXXScopeSpec &SS,
                                         const LookupResult &R) {
  CXXRecordDecl *BaseRecord =
    cast_or_null<CXXRecordDecl>(computeDeclContext(BaseType));
  if (!BaseRecord) {
    // We can't check this yet because the base type is still
    // dependent.
    assert(BaseType->isDependentType());
    return false;
  }

  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
    // If this is an implicit member reference and we find a
    // non-instance member, it's not an error.
    if (!BaseExpr && !(*I)->isCXXInstanceMember())
      return false;

    // Note that we use the DC of the decl, not the underlying decl.
    DeclContext *DC = (*I)->getDeclContext();
    while (DC->isTransparentContext())
      DC = DC->getParent();

    if (!DC->isRecord())
      continue;

    CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
    if (BaseRecord->getCanonicalDecl() == MemberRecord ||
        !BaseRecord->isProvablyNotDerivedFrom(MemberRecord))
      return false;
  }

  DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS,
                                   R.getRepresentativeDecl(),
                                   R.getLookupNameInfo());
  return true;
}

namespace {

// Callback to only accept typo corrections that are either a ValueDecl or a
// FunctionTemplateDecl and are declared in the current record or, for a C++
// classes, one of its base classes.
class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
public:
  explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
      : Record(RTy->getDecl()) {
    // Don't add bare keywords to the consumer since they will always fail
    // validation by virtue of not being associated with any decls.
    WantTypeSpecifiers = false;
    WantExpressionKeywords = false;
    WantCXXNamedCasts = false;
    WantFunctionLikeCasts = false;
    WantRemainingKeywords = false;
  }

  bool ValidateCandidate(const TypoCorrection &candidate) override {
    NamedDecl *ND = candidate.getCorrectionDecl();
    // Don't accept candidates that cannot be member functions, constants,
    // variables, or templates.
    if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)))
      return false;

    // Accept candidates that occur in the current record.
    if (Record->containsDecl(ND))
      return true;

    if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) {
      // Accept candidates that occur in any of the current class' base classes.
      for (const auto &BS : RD->bases()) {
        if (const RecordType *BSTy =
                dyn_cast_or_null<RecordType>(BS.getType().getTypePtrOrNull())) {
          if (BSTy->getDecl()->containsDecl(ND))
            return true;
        }
      }
    }

    return false;
  }

  std::unique_ptr<CorrectionCandidateCallback> clone() override {
    return std::make_unique<RecordMemberExprValidatorCCC>(*this);
  }

private:
  const RecordDecl *const Record;
};

}

static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
                                     Expr *BaseExpr,
                                     const RecordType *RTy,
                                     SourceLocation OpLoc, bool IsArrow,
                                     CXXScopeSpec &SS, bool HasTemplateArgs,
                                     SourceLocation TemplateKWLoc,
                                     TypoExpr *&TE) {
  SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
  RecordDecl *RDecl = RTy->getDecl();
  if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
      SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
                                  diag::err_typecheck_incomplete_tag,
                                  BaseRange))
    return true;

  if (HasTemplateArgs || TemplateKWLoc.isValid()) {
    // LookupTemplateName doesn't expect these both to exist simultaneously.
    QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);

    bool MOUS;
    return SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS,
                                      TemplateKWLoc);
  }

  DeclContext *DC = RDecl;
  if (SS.isSet()) {
    // If the member name was a qualified-id, look into the
    // nested-name-specifier.
    DC = SemaRef.computeDeclContext(SS, false);

    if (SemaRef.RequireCompleteDeclContext(SS, DC)) {
      SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
          << SS.getRange() << DC;
      return true;
    }

    assert(DC && "Cannot handle non-computable dependent contexts in lookup");

    if (!isa<TypeDecl>(DC)) {
      SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass)
          << DC << SS.getRange();
      return true;
    }
  }

  // The record definition is complete, now look up the member.
  SemaRef.LookupQualifiedName(R, DC, SS);

  if (!R.empty())
    return false;

  DeclarationName Typo = R.getLookupName();
  SourceLocation TypoLoc = R.getNameLoc();

  struct QueryState {
    Sema &SemaRef;
    DeclarationNameInfo NameInfo;
    Sema::LookupNameKind LookupKind;
    Sema::RedeclarationKind Redecl;
  };
  QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
                  R.redeclarationKind()};
  RecordMemberExprValidatorCCC CCC(RTy);
  TE = SemaRef.CorrectTypoDelayed(
      R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC,
      [=, &SemaRef](const TypoCorrection &TC) {
        if (TC) {
          assert(!TC.isKeyword() &&
                 "Got a keyword as a correction for a member!");
          bool DroppedSpecifier =
              TC.WillReplaceSpecifier() &&
              Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts());
          SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
                                       << Typo << DC << DroppedSpecifier
                                       << SS.getRange());
        } else {
          SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << DC << BaseRange;
        }
      },
      [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {
        LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl);
        R.clear(); // Ensure there's no decls lingering in the shared state.
        R.suppressDiagnostics();
        R.setLookupName(TC.getCorrection());
        for (NamedDecl *ND : TC)
          R.addDecl(ND);
        R.resolveKind();
        return SemaRef.BuildMemberReferenceExpr(
            BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),
            nullptr, R, nullptr, nullptr);
      },
      Sema::CTK_ErrorRecovery, DC);

  return false;
}

static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
                                   ExprResult &BaseExpr, bool &IsArrow,
                                   SourceLocation OpLoc, CXXScopeSpec &SS,
                                   Decl *ObjCImpDecl, bool HasTemplateArgs,
                                   SourceLocation TemplateKWLoc);

ExprResult
Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
                               SourceLocation OpLoc, bool IsArrow,
                               CXXScopeSpec &SS,
                               SourceLocation TemplateKWLoc,
                               NamedDecl *FirstQualifierInScope,
                               const DeclarationNameInfo &NameInfo,
                               const TemplateArgumentListInfo *TemplateArgs,
                               const Scope *S,
                               ActOnMemberAccessExtraArgs *ExtraArgs) {
  if (BaseType->isDependentType() ||
      (SS.isSet() && isDependentScopeSpecifier(SS)))
    return ActOnDependentMemberExpr(Base, BaseType,
                                    IsArrow, OpLoc,
                                    SS, TemplateKWLoc, FirstQualifierInScope,
                                    NameInfo, TemplateArgs);

  LookupResult R(*this, NameInfo, LookupMemberName);

  // Implicit member accesses.
  if (!Base) {
    TypoExpr *TE = nullptr;
    QualType RecordTy = BaseType;
    if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
    if (LookupMemberExprInRecord(
            *this, R, nullptr, RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
            SS, TemplateArgs != nullptr, TemplateKWLoc, TE))
      return ExprError();
    if (TE)
      return TE;

  // Explicit member accesses.
  } else {
    ExprResult BaseResult = Base;
    ExprResult Result =
        LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS,
                         ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
                         TemplateArgs != nullptr, TemplateKWLoc);

    if (BaseResult.isInvalid())
      return ExprError();
    Base = BaseResult.get();

    if (Result.isInvalid())
      return ExprError();

    if (Result.get())
      return Result;

    // LookupMemberExpr can modify Base, and thus change BaseType
    BaseType = Base->getType();
  }

  return BuildMemberReferenceExpr(Base, BaseType,
                                  OpLoc, IsArrow, SS, TemplateKWLoc,
                                  FirstQualifierInScope, R, TemplateArgs, S,
                                  false, ExtraArgs);
}

ExprResult
Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
                                               SourceLocation loc,
                                               IndirectFieldDecl *indirectField,
                                               DeclAccessPair foundDecl,
                                               Expr *baseObjectExpr,
                                               SourceLocation opLoc) {
  // First, build the expression that refers to the base object.

  // Case 1:  the base of the indirect field is not a field.
  VarDecl *baseVariable = indirectField->getVarDecl();
  CXXScopeSpec EmptySS;
  if (baseVariable) {
    assert(baseVariable->getType()->isRecordType());

    // In principle we could have a member access expression that
    // accesses an anonymous struct/union that's a static member of
    // the base object's class.  However, under the current standard,
    // static data members cannot be anonymous structs or unions.
    // Supporting this is as easy as building a MemberExpr here.
    assert(!baseObjectExpr && "anonymous struct/union is static data member?");

    DeclarationNameInfo baseNameInfo(DeclarationName(), loc);

    ExprResult result
      = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
    if (result.isInvalid()) return ExprError();

    baseObjectExpr = result.get();
  }

  assert((baseVariable || baseObjectExpr) &&
         "referencing anonymous struct/union without a base variable or "
         "expression");

  // Build the implicit member references to the field of the
  // anonymous struct/union.
  Expr *result = baseObjectExpr;
  IndirectFieldDecl::chain_iterator
  FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();

  // Case 2: the base of the indirect field is a field and the user
  // wrote a member expression.
  if (!baseVariable) {
    FieldDecl *field = cast<FieldDecl>(*FI);

    bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType();

    // Make a nameInfo that properly uses the anonymous name.
    DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);

    // Build the first member access in the chain with full information.
    result =
        BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(),
                                SS, field, foundDecl, memberNameInfo)
            .get();
    if (!result)
      return ExprError();
  }

  // In all cases, we should now skip the first declaration in the chain.
  ++FI;

  while (FI != FEnd) {
    FieldDecl *field = cast<FieldDecl>(*FI++);

    // FIXME: these are somewhat meaningless
    DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
    DeclAccessPair fakeFoundDecl =
        DeclAccessPair::make(field, field->getAccess());

    result =
        BuildFieldReferenceExpr(result, /*isarrow*/ false, SourceLocation(),
                                (FI == FEnd ? SS : EmptySS), field,
                                fakeFoundDecl, memberNameInfo)
            .get();
  }

  return result;
}

static ExprResult
BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
                       const CXXScopeSpec &SS,
                       MSPropertyDecl *PD,
                       const DeclarationNameInfo &NameInfo) {
  // Property names are always simple identifiers and therefore never
  // require any interesting additional storage.
  return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,
                                           S.Context.PseudoObjectTy, VK_LValue,
                                           SS.getWithLocInContext(S.Context),
                                           NameInfo.getLoc());
}

MemberExpr *Sema::BuildMemberExpr(
    Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS,
    SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
    bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
    QualType Ty, ExprValueKind VK, ExprObjectKind OK,
    const TemplateArgumentListInfo *TemplateArgs) {
  NestedNameSpecifierLoc NNS =
      SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc();
  return BuildMemberExpr(Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member,
                         FoundDecl, HadMultipleCandidates, MemberNameInfo, Ty,
                         VK, OK, TemplateArgs);
}

MemberExpr *Sema::BuildMemberExpr(
    Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS,
    SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
    bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
    QualType Ty, ExprValueKind VK, ExprObjectKind OK,
    const TemplateArgumentListInfo *TemplateArgs) {
  assert((!IsArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
  MemberExpr *E =
      MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc,
                         Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty,
                         VK, OK, getNonOdrUseReasonInCurrentContext(Member));
  E->setHadMultipleCandidates(HadMultipleCandidates);
  MarkMemberReferenced(E);

  // C++ [except.spec]p17:
  //   An exception-specification is considered to be needed when:
  //   - in an expression the function is the unique lookup result or the
  //     selected member of a set of overloaded functions
  if (auto *FPT = Ty->getAs<FunctionProtoType>()) {
    if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
      if (auto *NewFPT = ResolveExceptionSpec(MemberNameInfo.getLoc(), FPT))
        E->setType(Context.getQualifiedType(NewFPT, Ty.getQualifiers()));
    }
  }

  return E;
}

/// Determine if the given scope is within a function-try-block handler.
static bool IsInFnTryBlockHandler(const Scope *S) {
  // Walk the scope stack until finding a FnTryCatchScope, or leave the
  // function scope. If a FnTryCatchScope is found, check whether the TryScope
  // flag is set. If it is not, it's a function-try-block handler.
  for (; S != S->getFnParent(); S = S->getParent()) {
    if (S->getFlags() & Scope::FnTryCatchScope)
      return (S->getFlags() & Scope::TryScope) != Scope::TryScope;
  }
  return false;
}

ExprResult
Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
                               SourceLocation OpLoc, bool IsArrow,
                               const CXXScopeSpec &SS,
                               SourceLocation TemplateKWLoc,
                               NamedDecl *FirstQualifierInScope,
                               LookupResult &R,
                               const TemplateArgumentListInfo *TemplateArgs,
                               const Scope *S,
                               bool SuppressQualifierCheck,
                               ActOnMemberAccessExtraArgs *ExtraArgs) {
  QualType BaseType = BaseExprType;
  if (IsArrow) {
    assert(BaseType->isPointerType());
    BaseType = BaseType->castAs<PointerType>()->getPointeeType();
  }
  R.setBaseObjectType(BaseType);

  // C++1z [expr.ref]p2:
  //   For the first option (dot) the first expression shall be a glvalue [...]
  if (!IsArrow && BaseExpr && BaseExpr->isRValue()) {
    ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);
    if (Converted.isInvalid())
      return ExprError();
    BaseExpr = Converted.get();
  }


  const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
  DeclarationName MemberName = MemberNameInfo.getName();
  SourceLocation MemberLoc = MemberNameInfo.getLoc();

  if (R.isAmbiguous())
    return ExprError();

  // [except.handle]p10: Referring to any non-static member or base class of an
  // object in the handler for a function-try-block of a constructor or
  // destructor for that object results in undefined behavior.
  const auto *FD = getCurFunctionDecl();
  if (S && BaseExpr && FD &&
      (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
      isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) &&
      IsInFnTryBlockHandler(S))
    Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr)
        << isa<CXXDestructorDecl>(FD);

  if (R.empty()) {
    // Rederive where we looked up.
    DeclContext *DC = (SS.isSet()
                       ? computeDeclContext(SS, false)
                       : BaseType->castAs<RecordType>()->getDecl());

    if (ExtraArgs) {
      ExprResult RetryExpr;
      if (!IsArrow && BaseExpr) {
        SFINAETrap Trap(*this, true);
        ParsedType ObjectType;
        bool MayBePseudoDestructor = false;
        RetryExpr = ActOnStartCXXMemberReference(getCurScope(), BaseExpr,
                                                 OpLoc, tok::arrow, ObjectType,
                                                 MayBePseudoDestructor);
        if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {
          CXXScopeSpec TempSS(SS);
          RetryExpr = ActOnMemberAccessExpr(
              ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,
              TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);
        }
        if (Trap.hasErrorOccurred())
          RetryExpr = ExprError();
      }
      if (RetryExpr.isUsable()) {
        Diag(OpLoc, diag::err_no_member_overloaded_arrow)
          << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->");
        return RetryExpr;
      }
    }

    Diag(R.getNameLoc(), diag::err_no_member)
      << MemberName << DC
      << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange());
    return ExprError();
  }

  // Diagnose lookups that find only declarations from a non-base
  // type.  This is possible for either qualified lookups (which may
  // have been qualified with an unrelated type) or implicit member
  // expressions (which were found with unqualified lookup and thus
  // may have come from an enclosing scope).  Note that it's okay for
  // lookup to find declarations from a non-base type as long as those
  // aren't the ones picked by overload resolution.
  if ((SS.isSet() || !BaseExpr ||
       (isa<CXXThisExpr>(BaseExpr) &&
        cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&
      !SuppressQualifierCheck &&
      CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
    return ExprError();

  // Construct an unresolved result if we in fact got an unresolved
  // result.
  if (R.isOverloadedResult() || R.isUnresolvableResult()) {
    // Suppress any lookup-related diagnostics; we'll do these when we
    // pick a member.
    R.suppressDiagnostics();

    UnresolvedMemberExpr *MemExpr
      = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(),
                                     BaseExpr, BaseExprType,
                                     IsArrow, OpLoc,
                                     SS.getWithLocInContext(Context),
                                     TemplateKWLoc, MemberNameInfo,
                                     TemplateArgs, R.begin(), R.end());

    return MemExpr;
  }

  assert(R.isSingleResult());
  DeclAccessPair FoundDecl = R.begin().getPair();
  NamedDecl *MemberDecl = R.getFoundDecl();

  // FIXME: diagnose the presence of template arguments now.

  // If the decl being referenced had an error, return an error for this
  // sub-expr without emitting another error, in order to avoid cascading
  // error cases.
  if (MemberDecl->isInvalidDecl())
    return ExprError();

  // Handle the implicit-member-access case.
  if (!BaseExpr) {
    // If this is not an instance member, convert to a non-member access.
    if (!MemberDecl->isCXXInstanceMember()) {
      // We might have a variable template specialization (or maybe one day a
      // member concept-id).
      if (TemplateArgs || TemplateKWLoc.isValid())
        return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/false, TemplateArgs);

      return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl,
                                      FoundDecl, TemplateArgs);
    }
    SourceLocation Loc = R.getNameLoc();
    if (SS.getRange().isValid())
      Loc = SS.getRange().getBegin();
    BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true);
  }

  // Check the use of this member.
  if (DiagnoseUseOfDecl(MemberDecl, MemberLoc))
    return ExprError();

  if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
    return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl,
                                   MemberNameInfo);

  if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
    return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,
                                  MemberNameInfo);

  if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
    // We may have found a field within an anonymous union or struct
    // (C++ [class.union]).
    return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
                                                    FoundDecl, BaseExpr,
                                                    OpLoc);

  if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
    return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var,
                           FoundDecl, /*HadMultipleCandidates=*/false,
                           MemberNameInfo, Var->getType().getNonReferenceType(),
                           VK_LValue, OK_Ordinary);
  }

  if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
    ExprValueKind valueKind;
    QualType type;
    if (MemberFn->isInstance()) {
      valueKind = VK_RValue;
      type = Context.BoundMemberTy;
    } else {
      valueKind = VK_LValue;
      type = MemberFn->getType();
    }

    return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc,
                           MemberFn, FoundDecl, /*HadMultipleCandidates=*/false,
                           MemberNameInfo, type, valueKind, OK_Ordinary);
  }
  assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");

  if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
    return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Enum,
                           FoundDecl, /*HadMultipleCandidates=*/false,
                           MemberNameInfo, Enum->getType(), VK_RValue,
                           OK_Ordinary);
  }

  if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
    if (!TemplateArgs) {
      diagnoseMissingTemplateArguments(TemplateName(VarTempl), MemberLoc);
      return ExprError();
    }

    DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc,
                                          MemberNameInfo.getLoc(), *TemplateArgs);
    if (VDecl.isInvalid())
      return ExprError();

    // Non-dependent member, but dependent template arguments.
    if (!VDecl.get())
      return ActOnDependentMemberExpr(
          BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc,
          FirstQualifierInScope, MemberNameInfo, TemplateArgs);

    VarDecl *Var = cast<VarDecl>(VDecl.get());
    if (!Var->getTemplateSpecializationKind())
      Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc);

    return BuildMemberExpr(
        BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl,
        /*HadMultipleCandidates=*/false, MemberNameInfo,
        Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
  }

  // We found something that we didn't expect. Complain.
  if (isa<TypeDecl>(MemberDecl))
    Diag(MemberLoc, diag::err_typecheck_member_reference_type)
      << MemberName << BaseType << int(IsArrow);
  else
    Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)
      << MemberName << BaseType << int(IsArrow);

  Diag(MemberDecl->getLocation(), diag::note_member_declared_here)
    << MemberName;
  R.suppressDiagnostics();
  return ExprError();
}

/// Given that normal member access failed on the given expression,
/// and given that the expression's type involves builtin-id or
/// builtin-Class, decide whether substituting in the redefinition
/// types would be profitable.  The redefinition type is whatever
/// this translation unit tried to typedef to id/Class;  we store
/// it to the side and then re-use it in places like this.
static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) {
  const ObjCObjectPointerType *opty
    = base.get()->getType()->getAs<ObjCObjectPointerType>();
  if (!opty) return false;

  const ObjCObjectType *ty = opty->getObjectType();

  QualType redef;
  if (ty->isObjCId()) {
    redef = S.Context.getObjCIdRedefinitionType();
  } else if (ty->isObjCClass()) {
    redef = S.Context.getObjCClassRedefinitionType();
  } else {
    return false;
  }

  // Do the substitution as long as the redefinition type isn't just a
  // possibly-qualified pointer to builtin-id or builtin-Class again.
  opty = redef->getAs<ObjCObjectPointerType>();
  if (opty && !opty->getObjectType()->getInterface())
    return false;

  base = S.ImpCastExprToType(base.get(), redef, CK_BitCast);
  return true;
}

static bool isRecordType(QualType T) {
  return T->isRecordType();
}
static bool isPointerToRecordType(QualType T) {
  if (const PointerType *PT = T->getAs<PointerType>())
    return PT->getPointeeType()->isRecordType();
  return false;
}

/// Perform conversions on the LHS of a member access expression.
ExprResult
Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {
  if (IsArrow && !Base->getType()->isFunctionType())
    return DefaultFunctionArrayLvalueConversion(Base);

  return CheckPlaceholderExpr(Base);
}

/// Look up the given member of the given non-type-dependent
/// expression.  This can return in one of two ways:
///  * If it returns a sentinel null-but-valid result, the caller will
///    assume that lookup was performed and the results written into
///    the provided structure.  It will take over from there.
///  * Otherwise, the returned expression will be produced in place of
///    an ordinary member expression.
///
/// The ObjCImpDecl bit is a gross hack that will need to be properly
/// fixed for ObjC++.
static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
                                   ExprResult &BaseExpr, bool &IsArrow,
                                   SourceLocation OpLoc, CXXScopeSpec &SS,
                                   Decl *ObjCImpDecl, bool HasTemplateArgs,
                                   SourceLocation TemplateKWLoc) {
  assert(BaseExpr.get() && "no base expression");

  // Perform default conversions.
  BaseExpr = S.PerformMemberExprBaseConversion(BaseExpr.get(), IsArrow);
  if (BaseExpr.isInvalid())
    return ExprError();

  QualType BaseType = BaseExpr.get()->getType();
  assert(!BaseType->isDependentType());

  DeclarationName MemberName = R.getLookupName();
  SourceLocation MemberLoc = R.getNameLoc();

  // For later type-checking purposes, turn arrow accesses into dot
  // accesses.  The only access type we support that doesn't follow
  // the C equivalence "a->b === (*a).b" is ObjC property accesses,
  // and those never use arrows, so this is unaffected.
  if (IsArrow) {
    if (const PointerType *Ptr = BaseType->getAs<PointerType>())
      BaseType = Ptr->getPointeeType();
    else if (const ObjCObjectPointerType *Ptr
               = BaseType->getAs<ObjCObjectPointerType>())
      BaseType = Ptr->getPointeeType();
    else if (BaseType->isRecordType()) {
      // Recover from arrow accesses to records, e.g.:
      //   struct MyRecord foo;
      //   foo->bar
      // This is actually well-formed in C++ if MyRecord has an
      // overloaded operator->, but that should have been dealt with
      // by now--or a diagnostic message already issued if a problem
      // was encountered while looking for the overloaded operator->.
      if (!S.getLangOpts().CPlusPlus) {
        S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
          << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
          << FixItHint::CreateReplacement(OpLoc, ".");
      }
      IsArrow = false;
    } else if (BaseType->isFunctionType()) {
      goto fail;
    } else {
      S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
        << BaseType << BaseExpr.get()->getSourceRange();
      return ExprError();
    }
  }

  // Handle field access to simple records.
  if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
    TypoExpr *TE = nullptr;
    if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS,
                                 HasTemplateArgs, TemplateKWLoc, TE))
      return ExprError();

    // Returning valid-but-null is how we indicate to the caller that
    // the lookup result was filled in. If typo correction was attempted and
    // failed, the lookup result will have been cleared--that combined with the
    // valid-but-null ExprResult will trigger the appropriate diagnostics.
    return ExprResult(TE);
  }

  // Handle ivar access to Objective-C objects.
  if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) {
    if (!SS.isEmpty() && !SS.isInvalid()) {
      S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
        << 1 << SS.getScopeRep()
        << FixItHint::CreateRemoval(SS.getRange());
      SS.clear();
    }

    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();

    // There are three cases for the base type:
    //   - builtin id (qualified or unqualified)
    //   - builtin Class (qualified or unqualified)
    //   - an interface
    ObjCInterfaceDecl *IDecl = OTy->getInterface();
    if (!IDecl) {
      if (S.getLangOpts().ObjCAutoRefCount &&
          (OTy->isObjCId() || OTy->isObjCClass()))
        goto fail;
      // There's an implicit 'isa' ivar on all objects.
      // But we only actually find it this way on objects of type 'id',
      // apparently.
      if (OTy->isObjCId() && Member->isStr("isa"))
        return new (S.Context) ObjCIsaExpr(BaseExpr.get(), IsArrow, MemberLoc,
                                           OpLoc, S.Context.getObjCClassType());
      if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
        return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
                                ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
      goto fail;
    }

    if (S.RequireCompleteType(OpLoc, BaseType,
                              diag::err_typecheck_incomplete_tag,
                              BaseExpr.get()))
      return ExprError();

    ObjCInterfaceDecl *ClassDeclared = nullptr;
    ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);

    if (!IV) {
      // Attempt to correct for typos in ivar names.
      DeclFilterCCC<ObjCIvarDecl> Validator{};
      Validator.IsObjCIvarLookup = IsArrow;
      if (TypoCorrection Corrected = S.CorrectTypo(
              R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
              Validator, Sema::CTK_ErrorRecovery, IDecl)) {
        IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
        S.diagnoseTypo(
            Corrected,
            S.PDiag(diag::err_typecheck_member_reference_ivar_suggest)
                << IDecl->getDeclName() << MemberName);

        // Figure out the class that declares the ivar.
        assert(!ClassDeclared);

        Decl *D = cast<Decl>(IV->getDeclContext());
        if (auto *Category = dyn_cast<ObjCCategoryDecl>(D))
          D = Category->getClassInterface();

        if (auto *Implementation = dyn_cast<ObjCImplementationDecl>(D))
          ClassDeclared = Implementation->getClassInterface();
        else if (auto *Interface = dyn_cast<ObjCInterfaceDecl>(D))
          ClassDeclared = Interface;

        assert(ClassDeclared && "cannot query interface");
      } else {
        if (IsArrow &&
            IDecl->FindPropertyDeclaration(
                Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
          S.Diag(MemberLoc, diag::err_property_found_suggest)
              << Member << BaseExpr.get()->getType()
              << FixItHint::CreateReplacement(OpLoc, ".");
          return ExprError();
        }

        S.Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
            << IDecl->getDeclName() << MemberName
            << BaseExpr.get()->getSourceRange();
        return ExprError();
      }
    }

    assert(ClassDeclared);

    // If the decl being referenced had an error, return an error for this
    // sub-expr without emitting another error, in order to avoid cascading
    // error cases.
    if (IV->isInvalidDecl())
      return ExprError();

    // Check whether we can reference this field.
    if (S.DiagnoseUseOfDecl(IV, MemberLoc))
      return ExprError();
    if (IV->getAccessControl() != ObjCIvarDecl::Public &&
        IV->getAccessControl() != ObjCIvarDecl::Package) {
      ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;
      if (ObjCMethodDecl *MD = S.getCurMethodDecl())
        ClassOfMethodDecl =  MD->getClassInterface();
      else if (ObjCImpDecl && S.getCurFunctionDecl()) {
        // Case of a c-function declared inside an objc implementation.
        // FIXME: For a c-style function nested inside an objc implementation
        // class, there is no implementation context available, so we pass
        // down the context as argument to this routine. Ideally, this context
        // need be passed down in the AST node and somehow calculated from the
        // AST for a function decl.
        if (ObjCImplementationDecl *IMPD =
              dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))
          ClassOfMethodDecl = IMPD->getClassInterface();
        else if (ObjCCategoryImplDecl* CatImplClass =
                   dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl))
          ClassOfMethodDecl = CatImplClass->getClassInterface();
      }
      if (!S.getLangOpts().DebuggerSupport) {
        if (IV->getAccessControl() == ObjCIvarDecl::Private) {
          if (!declaresSameEntity(ClassDeclared, IDecl) ||
              !declaresSameEntity(ClassOfMethodDecl, ClassDeclared))
            S.Diag(MemberLoc, diag::err_private_ivar_access)
              << IV->getDeclName();
        } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
          // @protected
          S.Diag(MemberLoc, diag::err_protected_ivar_access)
              << IV->getDeclName();
      }
    }
    bool warn = true;
    if (S.getLangOpts().ObjCWeak) {
      Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts();
      if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp))
        if (UO->getOpcode() == UO_Deref)
          BaseExp = UO->getSubExpr()->IgnoreParenCasts();

      if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp))
        if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
          S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access);
          warn = false;
        }
    }
    if (warn) {
      if (ObjCMethodDecl *MD = S.getCurMethodDecl()) {
        ObjCMethodFamily MF = MD->getMethodFamily();
        warn = (MF != OMF_init && MF != OMF_dealloc &&
                MF != OMF_finalize &&
                !S.IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
      }
      if (warn)
        S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
    }

    ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr(
        IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(),
        IsArrow);

    if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
      if (!S.isUnevaluatedContext() &&
          !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
        S.getCurFunction()->recordUseOfWeak(Result);
    }

    return Result;
  }

  // Objective-C property access.
  const ObjCObjectPointerType *OPT;
  if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {
    if (!SS.isEmpty() && !SS.isInvalid()) {
      S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
          << 0 << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());
      SS.clear();
    }

    // This actually uses the base as an r-value.
    BaseExpr = S.DefaultLvalueConversion(BaseExpr.get());
    if (BaseExpr.isInvalid())
      return ExprError();

    assert(S.Context.hasSameUnqualifiedType(BaseType,
                                            BaseExpr.get()->getType()));

    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();

    const ObjCObjectType *OT = OPT->getObjectType();

    // id, with and without qualifiers.
    if (OT->isObjCId()) {
      // Check protocols on qualified interfaces.
      Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
      if (Decl *PMDecl =
              FindGetterSetterNameDecl(OPT, Member, Sel, S.Context)) {
        if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
          // Check the use of this declaration
          if (S.DiagnoseUseOfDecl(PD, MemberLoc))
            return ExprError();

          return new (S.Context)
              ObjCPropertyRefExpr(PD, S.Context.PseudoObjectTy, VK_LValue,
                                  OK_ObjCProperty, MemberLoc, BaseExpr.get());
        }

        if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
          Selector SetterSel =
            SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
                                                   S.PP.getSelectorTable(),
                                                   Member);
          ObjCMethodDecl *SMD = nullptr;
          if (Decl *SDecl = FindGetterSetterNameDecl(OPT,
                                                     /*Property id*/ nullptr,
                                                     SetterSel, S.Context))
            SMD = dyn_cast<ObjCMethodDecl>(SDecl);

          return new (S.Context)
              ObjCPropertyRefExpr(OMD, SMD, S.Context.PseudoObjectTy, VK_LValue,
                                  OK_ObjCProperty, MemberLoc, BaseExpr.get());
        }
      }
      // Use of id.member can only be for a property reference. Do not
      // use the 'id' redefinition in this case.
      if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr))
        return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
                                ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);

      return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
                         << MemberName << BaseType);
    }

    // 'Class', unqualified only.
    if (OT->isObjCClass()) {
      // Only works in a method declaration (??!).
      ObjCMethodDecl *MD = S.getCurMethodDecl();
      if (!MD) {
        if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
          return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
                                  ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);

        goto fail;
      }

      // Also must look for a getter name which uses property syntax.
      Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
      ObjCInterfaceDecl *IFace = MD->getClassInterface();
      if (!IFace)
        goto fail;

      ObjCMethodDecl *Getter;
      if ((Getter = IFace->lookupClassMethod(Sel))) {
        // Check the use of this method.
        if (S.DiagnoseUseOfDecl(Getter, MemberLoc))
          return ExprError();
      } else
        Getter = IFace->lookupPrivateMethod(Sel, false);
      // If we found a getter then this may be a valid dot-reference, we
      // will look for the matching setter, in case it is needed.
      Selector SetterSel =
        SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
                                               S.PP.getSelectorTable(),
                                               Member);
      ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
      if (!Setter) {
        // If this reference is in an @implementation, also check for 'private'
        // methods.
        Setter = IFace->lookupPrivateMethod(SetterSel, false);
      }

      if (Setter && S.DiagnoseUseOfDecl(Setter, MemberLoc))
        return ExprError();

      if (Getter || Setter) {
        return new (S.Context) ObjCPropertyRefExpr(
            Getter, Setter, S.Context.PseudoObjectTy, VK_LValue,
            OK_ObjCProperty, MemberLoc, BaseExpr.get());
      }

      if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
        return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
                                ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);

      return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
                         << MemberName << BaseType);
    }

    // Normal property access.
    return S.HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc, MemberName,
                                       MemberLoc, SourceLocation(), QualType(),
                                       false);
  }

  // Handle 'field access' to vectors, such as 'V.xx'.
  if (BaseType->isExtVectorType()) {
    // FIXME: this expr should store IsArrow.
    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
    ExprValueKind VK;
    if (IsArrow)
      VK = VK_LValue;
    else {
      if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(BaseExpr.get()))
        VK = POE->getSyntacticForm()->getValueKind();
      else
        VK = BaseExpr.get()->getValueKind();
    }

    QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,
                                           Member, MemberLoc);
    if (ret.isNull())
      return ExprError();
    Qualifiers BaseQ =
        S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers();
    ret = S.Context.getQualifiedType(ret, BaseQ);

    return new (S.Context)
        ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc);
  }

  // Adjust builtin-sel to the appropriate redefinition type if that's
  // not just a pointer to builtin-sel again.
  if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&
      !S.Context.getObjCSelRedefinitionType()->isObjCSelType()) {
    BaseExpr = S.ImpCastExprToType(
        BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast);
    return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
                            ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
  }

  // Failure cases.
 fail:

  // Recover from dot accesses to pointers, e.g.:
  //   type *foo;
  //   foo.bar
  // This is actually well-formed in two cases:
  //   - 'type' is an Objective C type
  //   - 'bar' is a pseudo-destructor name which happens to refer to
  //     the appropriate pointer type
  if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
    if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
        MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
      S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
          << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
          << FixItHint::CreateReplacement(OpLoc, "->");

      // Recurse as an -> access.
      IsArrow = true;
      return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
                              ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
    }
  }

  // If the user is trying to apply -> or . to a function name, it's probably
  // because they forgot parentheses to call that function.
  if (S.tryToRecoverWithCall(
          BaseExpr, S.PDiag(diag::err_member_reference_needs_call),
          /*complain*/ false,
          IsArrow ? &isPointerToRecordType : &isRecordType)) {
    if (BaseExpr.isInvalid())
      return ExprError();
    BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get());
    return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
                            ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
  }

  S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
    << BaseType << BaseExpr.get()->getSourceRange() << MemberLoc;

  return ExprError();
}

/// The main callback when the parser finds something like
///   expression . [nested-name-specifier] identifier
///   expression -> [nested-name-specifier] identifier
/// where 'identifier' encompasses a fairly broad spectrum of
/// possibilities, including destructor and operator references.
///
/// \param OpKind either tok::arrow or tok::period
/// \param ObjCImpDecl the current Objective-C \@implementation
///   decl; this is an ugly hack around the fact that Objective-C
///   \@implementations aren't properly put in the context chain
ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
                                       SourceLocation OpLoc,
                                       tok::TokenKind OpKind,
                                       CXXScopeSpec &SS,
                                       SourceLocation TemplateKWLoc,
                                       UnqualifiedId &Id,
                                       Decl *ObjCImpDecl) {
  if (SS.isSet() && SS.isInvalid())
    return ExprError();

  // Warn about the explicit constructor calls Microsoft extension.
  if (getLangOpts().MicrosoftExt &&
      Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
    Diag(Id.getSourceRange().getBegin(),
         diag::ext_ms_explicit_constructor_call);

  TemplateArgumentListInfo TemplateArgsBuffer;

  // Decompose the name into its component parts.
  DeclarationNameInfo NameInfo;
  const TemplateArgumentListInfo *TemplateArgs;
  DecomposeUnqualifiedId(Id, TemplateArgsBuffer,
                         NameInfo, TemplateArgs);

  DeclarationName Name = NameInfo.getName();
  bool IsArrow = (OpKind == tok::arrow);

  NamedDecl *FirstQualifierInScope
    = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep()));

  // This is a postfix expression, so get rid of ParenListExprs.
  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
  if (Result.isInvalid()) return ExprError();
  Base = Result.get();

  if (Base->getType()->isDependentType() || Name.isDependentName() ||
      isDependentScopeSpecifier(SS)) {
    return ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, SS,
                                    TemplateKWLoc, FirstQualifierInScope,
                                    NameInfo, TemplateArgs);
  }

  ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
  ExprResult Res = BuildMemberReferenceExpr(
      Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc,
      FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs);

  if (!Res.isInvalid() && isa<MemberExpr>(Res.get()))
    CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get()));

  return Res;
}

void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {
  if (isUnevaluatedContext())
    return;

  QualType ResultTy = E->getType();

  // Member accesses have four cases:
  // 1: non-array member via "->": dereferences
  // 2: non-array member via ".": nothing interesting happens
  // 3: array member access via "->": nothing interesting happens
  //    (this returns an array lvalue and does not actually dereference memory)
  // 4: array member access via ".": *adds* a layer of indirection
  if (ResultTy->isArrayType()) {
    if (!E->isArrow()) {
      // This might be something like:
      //     (*structPtr).arrayMember
      // which behaves roughly like:
      //     &(*structPtr).pointerMember
      // in that the apparent dereference in the base expression does not
      // actually happen.
      CheckAddressOfNoDeref(E->getBase());
    }
  } else if (E->isArrow()) {
    if (const auto *Ptr = dyn_cast<PointerType>(
            E->getBase()->getType().getDesugaredType(Context))) {
      if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
        ExprEvalContexts.back().PossibleDerefs.insert(E);
    }
  }
}

ExprResult
Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
                              SourceLocation OpLoc, const CXXScopeSpec &SS,
                              FieldDecl *Field, DeclAccessPair FoundDecl,
                              const DeclarationNameInfo &MemberNameInfo) {
  // x.a is an l-value if 'a' has a reference type. Otherwise:
  // x.a is an l-value/x-value/pr-value if the base is (and note
  //   that *x is always an l-value), except that if the base isn't
  //   an ordinary object then we must have an rvalue.
  ExprValueKind VK = VK_LValue;
  ExprObjectKind OK = OK_Ordinary;
  if (!IsArrow) {
    if (BaseExpr->getObjectKind() == OK_Ordinary)
      VK = BaseExpr->getValueKind();
    else
      VK = VK_RValue;
  }
  if (VK != VK_RValue && Field->isBitField())
    OK = OK_BitField;

  // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
  QualType MemberType = Field->getType();
  if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
    MemberType = Ref->getPointeeType();
    VK = VK_LValue;
  } else {
    QualType BaseType = BaseExpr->getType();
    if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType();

    Qualifiers BaseQuals = BaseType.getQualifiers();

    // GC attributes are never picked up by members.
    BaseQuals.removeObjCGCAttr();

    // CVR attributes from the base are picked up by members,
    // except that 'mutable' members don't pick up 'const'.
    if (Field->isMutable()) BaseQuals.removeConst();

    Qualifiers MemberQuals =
        Context.getCanonicalType(MemberType).getQualifiers();

    assert(!MemberQuals.hasAddressSpace());

    Qualifiers Combined = BaseQuals + MemberQuals;
    if (Combined != MemberQuals)
      MemberType = Context.getQualifiedType(MemberType, Combined);

    // Pick up NoDeref from the base in case we end up using AddrOf on the
    // result. E.g. the expression
    //     &someNoDerefPtr->pointerMember
    // should be a noderef pointer again.
    if (BaseType->hasAttr(attr::NoDeref))
      MemberType =
          Context.getAttributedType(attr::NoDeref, MemberType, MemberType);
  }

  auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
  if (!(CurMethod && CurMethod->isDefaulted()))
    UnusedPrivateFields.remove(Field);

  ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
                                                  FoundDecl, Field);
  if (Base.isInvalid())
    return ExprError();

  // Build a reference to a private copy for non-static data members in
  // non-static member functions, privatized by OpenMP constructs.
  if (getLangOpts().OpenMP && IsArrow &&
      !CurContext->isDependentContext() &&
      isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
    if (auto *PrivateCopy = isOpenMPCapturedDecl(Field)) {
      return getOpenMPCapturedExpr(PrivateCopy, VK, OK,
                                   MemberNameInfo.getLoc());
    }
  }

  return BuildMemberExpr(Base.get(), IsArrow, OpLoc, &SS,
                         /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,
                         /*HadMultipleCandidates=*/false, MemberNameInfo,
                         MemberType, VK, OK);
}

/// Builds an implicit member access expression.  The current context
/// is known to be an instance method, and the given unqualified lookup
/// set is known to contain only instance members, at least one of which
/// is from an appropriate type.
ExprResult
Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
                              SourceLocation TemplateKWLoc,
                              LookupResult &R,
                              const TemplateArgumentListInfo *TemplateArgs,
                              bool IsKnownInstance, const Scope *S) {
  assert(!R.empty() && !R.isAmbiguous());

  SourceLocation loc = R.getNameLoc();

  // If this is known to be an instance access, go ahead and build an
  // implicit 'this' expression now.
  QualType ThisTy = getCurrentThisType();
  assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");

  Expr *baseExpr = nullptr; // null signifies implicit access
  if (IsKnownInstance) {
    SourceLocation Loc = R.getNameLoc();
    if (SS.getRange().isValid())
      Loc = SS.getRange().getBegin();
    baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true);
  }

  return BuildMemberReferenceExpr(baseExpr, ThisTy,
                                  /*OpLoc*/ SourceLocation(),
                                  /*IsArrow*/ true,
                                  SS, TemplateKWLoc,
                                  /*FirstQualifierInScope*/ nullptr,
                                  R, TemplateArgs, S);
}
