brintos

brintos / llvm-project-archived public Read only

0
0
Text · 74.0 KiB · aedfc5e Raw
1879 lines · cpp
1//===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file implements semantic analysis member access expressions.10//11//===----------------------------------------------------------------------===//12#include "clang/AST/DeclCXX.h"13#include "clang/AST/DeclObjC.h"14#include "clang/AST/DeclTemplate.h"15#include "clang/AST/ExprCXX.h"16#include "clang/AST/ExprObjC.h"17#include "clang/Lex/Preprocessor.h"18#include "clang/Sema/Lookup.h"19#include "clang/Sema/Overload.h"20#include "clang/Sema/Scope.h"21#include "clang/Sema/ScopeInfo.h"22#include "clang/Sema/SemaObjC.h"23#include "clang/Sema/SemaOpenMP.h"24 25using namespace clang;26using namespace sema;27 28typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet;29 30/// Determines if the given class is provably not derived from all of31/// the prospective base classes.32static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record,33                                     const BaseSet &Bases) {34  auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) {35    return !Bases.count(Base->getCanonicalDecl());36  };37  return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet);38}39 40enum IMAKind {41  /// The reference is definitely not an instance member access.42  IMA_Static,43 44  /// The reference may be an implicit instance member access.45  IMA_Mixed,46 47  /// The reference may be to an instance member, but it might be invalid if48  /// so, because the context is not an instance method.49  IMA_Mixed_StaticOrExplicitContext,50 51  /// The reference may be to an instance member, but it is invalid if52  /// so, because the context is from an unrelated class.53  IMA_Mixed_Unrelated,54 55  /// The reference is definitely an implicit instance member access.56  IMA_Instance,57 58  /// The reference may be to an unresolved using declaration.59  IMA_Unresolved,60 61  /// The reference is a contextually-permitted abstract member reference.62  IMA_Abstract,63 64  /// Whether the context is static is dependent on the enclosing template (i.e.65  /// in a dependent class scope explicit specialization).66  IMA_Dependent,67 68  /// The reference may be to an unresolved using declaration and the69  /// context is not an instance method.70  IMA_Unresolved_StaticOrExplicitContext,71 72  // The reference refers to a field which is not a member of the containing73  // class, which is allowed because we're in C++11 mode and the context is74  // unevaluated.75  IMA_Field_Uneval_Context,76 77  /// All possible referrents are instance members and the current78  /// context is not an instance method.79  IMA_Error_StaticOrExplicitContext,80 81  /// All possible referrents are instance members of an unrelated82  /// class.83  IMA_Error_Unrelated84};85 86/// The given lookup names class member(s) and is not being used for87/// an address-of-member expression.  Classify the type of access88/// according to whether it's possible that this reference names an89/// instance member.  This is best-effort in dependent contexts; it is okay to90/// conservatively answer "yes", in which case some errors will simply91/// not be caught until template-instantiation.92static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,93                                            const LookupResult &R) {94  assert(!R.empty() && (*R.begin())->isCXXClassMember());95 96  DeclContext *DC = SemaRef.getFunctionLevelDeclContext();97 98  bool couldInstantiateToStatic = false;99  bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull();100 101  if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) {102    if (MD->isImplicitObjectMemberFunction()) {103      isStaticOrExplicitContext = false;104      // A dependent class scope function template explicit specialization105      // that is neither declared 'static' nor with an explicit object106      // parameter could instantiate to a static or non-static member function.107      couldInstantiateToStatic = MD->getDependentSpecializationInfo();108    }109  }110 111  if (R.isUnresolvableResult()) {112    if (couldInstantiateToStatic)113      return IMA_Dependent;114    return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext115                                     : IMA_Unresolved;116  }117 118  // Collect all the declaring classes of instance members we find.119  bool hasNonInstance = false;120  bool isField = false;121  BaseSet Classes;122  for (NamedDecl *D : R) {123    // Look through any using decls.124    D = D->getUnderlyingDecl();125 126    if (D->isCXXInstanceMember()) {127      isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) ||128                 isa<IndirectFieldDecl>(D);129 130      CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());131      Classes.insert(R->getCanonicalDecl());132    } else133      hasNonInstance = true;134  }135 136  // If we didn't find any instance members, it can't be an implicit137  // member reference.138  if (Classes.empty())139    return IMA_Static;140 141  if (couldInstantiateToStatic)142    return IMA_Dependent;143 144  // C++11 [expr.prim.general]p12:145  //   An id-expression that denotes a non-static data member or non-static146  //   member function of a class can only be used:147  //   (...)148  //   - if that id-expression denotes a non-static data member and it149  //     appears in an unevaluated operand.150  //151  // This rule is specific to C++11.  However, we also permit this form152  // in unevaluated inline assembly operands, like the operand to a SIZE.153  IMAKind AbstractInstanceResult = IMA_Static; // happens to be 'false'154  assert(!AbstractInstanceResult);155  switch (SemaRef.ExprEvalContexts.back().Context) {156  case Sema::ExpressionEvaluationContext::Unevaluated:157  case Sema::ExpressionEvaluationContext::UnevaluatedList:158    if (isField && SemaRef.getLangOpts().CPlusPlus11)159      AbstractInstanceResult = IMA_Field_Uneval_Context;160    break;161 162  case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:163    AbstractInstanceResult = IMA_Abstract;164    break;165 166  case Sema::ExpressionEvaluationContext::DiscardedStatement:167  case Sema::ExpressionEvaluationContext::ConstantEvaluated:168  case Sema::ExpressionEvaluationContext::ImmediateFunctionContext:169  case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:170  case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:171    break;172  }173 174  // If the current context is not an instance method, it can't be175  // an implicit member reference.176  if (isStaticOrExplicitContext) {177    if (hasNonInstance)178      return IMA_Mixed_StaticOrExplicitContext;179 180    return AbstractInstanceResult ? AbstractInstanceResult181                                  : IMA_Error_StaticOrExplicitContext;182  }183 184  CXXRecordDecl *contextClass;185  if (auto *MD = dyn_cast<CXXMethodDecl>(DC))186    contextClass = MD->getParent()->getCanonicalDecl();187  else if (auto *RD = dyn_cast<CXXRecordDecl>(DC))188    contextClass = RD;189  else190    return AbstractInstanceResult ? AbstractInstanceResult191                                  : IMA_Error_StaticOrExplicitContext;192 193  // [class.mfct.non-static]p3:194  // ...is used in the body of a non-static member function of class X,195  // if name lookup (3.4.1) resolves the name in the id-expression to a196  // non-static non-type member of some class C [...]197  // ...if C is not X or a base class of X, the class member access expression198  // is ill-formed.199  if (R.getNamingClass() &&200      contextClass->getCanonicalDecl() !=201        R.getNamingClass()->getCanonicalDecl()) {202    // If the naming class is not the current context, this was a qualified203    // member name lookup, and it's sufficient to check that we have the naming204    // class as a base class.205    Classes.clear();206    Classes.insert(R.getNamingClass()->getCanonicalDecl());207  }208 209  // If we can prove that the current context is unrelated to all the210  // declaring classes, it can't be an implicit member reference (in211  // which case it's an error if any of those members are selected).212  if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes))213    return hasNonInstance ? IMA_Mixed_Unrelated :214           AbstractInstanceResult ? AbstractInstanceResult :215                                    IMA_Error_Unrelated;216 217  return (hasNonInstance ? IMA_Mixed : IMA_Instance);218}219 220/// Diagnose a reference to a field with no object available.221static void diagnoseInstanceReference(Sema &SemaRef,222                                      const CXXScopeSpec &SS,223                                      NamedDecl *Rep,224                                      const DeclarationNameInfo &nameInfo) {225  SourceLocation Loc = nameInfo.getLoc();226  SourceRange Range(Loc);227  if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());228 229  // Look through using shadow decls and aliases.230  Rep = Rep->getUnderlyingDecl();231 232  DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();233  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);234  CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;235  CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());236 237  bool InStaticMethod = Method && Method->isStatic();238  bool InExplicitObjectMethod =239      Method && Method->isExplicitObjectMemberFunction();240  bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep);241 242  std::string Replacement;243  if (InExplicitObjectMethod) {244    DeclarationName N = Method->getParamDecl(0)->getDeclName();245    if (!N.isEmpty()) {246      Replacement.append(N.getAsString());247      Replacement.append(".");248    }249  }250  if (IsField && InStaticMethod)251    // "invalid use of member 'x' in static member function"252    SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)253        << Range << nameInfo.getName() << /*static*/ 0;254  else if (IsField && InExplicitObjectMethod) {255    auto Diag = SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)256                << Range << nameInfo.getName() << /*explicit*/ 1;257    if (!Replacement.empty())258      Diag << FixItHint::CreateInsertion(Loc, Replacement);259  } else if (ContextClass && RepClass && SS.isEmpty() &&260             !InExplicitObjectMethod && !InStaticMethod &&261             !RepClass->Equals(ContextClass) &&262             RepClass->Encloses(ContextClass))263    // Unqualified lookup in a non-static member function found a member of an264    // enclosing class.265    SemaRef.Diag(Loc, diag::err_nested_non_static_member_use)266      << IsField << RepClass << nameInfo.getName() << ContextClass << Range;267  else if (IsField)268    SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)269      << nameInfo.getName() << Range;270  else if (!InExplicitObjectMethod)271    SemaRef.Diag(Loc, diag::err_member_call_without_object)272        << Range << /*static*/ 0;273  else {274    if (const auto *Tpl = dyn_cast<FunctionTemplateDecl>(Rep))275      Rep = Tpl->getTemplatedDecl();276    const auto *Callee = cast<CXXMethodDecl>(Rep);277    auto Diag = SemaRef.Diag(Loc, diag::err_member_call_without_object)278                << Range << Callee->isExplicitObjectMemberFunction();279    if (!Replacement.empty())280      Diag << FixItHint::CreateInsertion(Loc, Replacement);281  }282}283 284bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS,285                                           LookupResult &R,286                                           bool IsAddressOfOperand) {287  if (!getLangOpts().CPlusPlus)288    return false;289  else if (R.empty() || !R.begin()->isCXXClassMember())290    return false;291  else if (!IsAddressOfOperand)292    return true;293  else if (!SS.isEmpty())294    return false;295  else if (R.isOverloadedResult())296    return false;297  else if (R.isUnresolvableResult())298    return true;299  else300    return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl());301}302 303ExprResult Sema::BuildPossibleImplicitMemberExpr(304    const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,305    const TemplateArgumentListInfo *TemplateArgs, const Scope *S) {306  switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {307  case IMA_Instance:308  case IMA_Mixed:309  case IMA_Mixed_Unrelated:310  case IMA_Unresolved:311    return BuildImplicitMemberExpr(312        SS, TemplateKWLoc, R, TemplateArgs,313        /*IsKnownInstance=*/Classification == IMA_Instance, S);314  case IMA_Field_Uneval_Context:315    Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)316      << R.getLookupNameInfo().getName();317    [[fallthrough]];318  case IMA_Static:319  case IMA_Abstract:320  case IMA_Mixed_StaticOrExplicitContext:321  case IMA_Unresolved_StaticOrExplicitContext:322    if (TemplateArgs || TemplateKWLoc.isValid())323      return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,324                                 TemplateArgs);325    return BuildDeclarationNameExpr(SS, R, /*NeedsADL=*/false,326                                    /*AcceptInvalidDecl=*/false);327  case IMA_Dependent:328    R.suppressDiagnostics();329    return UnresolvedLookupExpr::Create(330        Context, R.getNamingClass(), SS.getWithLocInContext(Context),331        TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false,332        TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true,333        /*KnownInstantiationDependent=*/true);334 335  case IMA_Error_StaticOrExplicitContext:336  case IMA_Error_Unrelated:337    diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),338                              R.getLookupNameInfo());339    return ExprError();340  }341 342  llvm_unreachable("unexpected instance member access kind");343}344 345/// Determine whether input char is from rgba component set.346static bool347IsRGBA(char c) {348  switch (c) {349  case 'r':350  case 'g':351  case 'b':352  case 'a':353    return true;354  default:355    return false;356  }357}358 359// OpenCL v1.1, s6.1.7360// The component swizzle length must be in accordance with the acceptable361// vector sizes.362static bool IsValidOpenCLComponentSwizzleLength(unsigned len)363{364  return (len >= 1 && len <= 4) || len == 8 || len == 16;365}366 367/// Check an ext-vector component access expression.368///369/// VK should be set in advance to the value kind of the base370/// expression.371static QualType372CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,373                        SourceLocation OpLoc, const IdentifierInfo *CompName,374                        SourceLocation CompLoc) {375  // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,376  // see FIXME there.377  //378  // FIXME: This logic can be greatly simplified by splitting it along379  // halving/not halving and reworking the component checking.380  const ExtVectorType *vecType = baseType->castAs<ExtVectorType>();381 382  // The vector accessor can't exceed the number of elements.383  const char *compStr = CompName->getNameStart();384 385  // This flag determines whether or not the component is one of the four386  // special names that indicate a subset of exactly half the elements are387  // to be selected.388  bool HalvingSwizzle = false;389 390  // This flag determines whether or not CompName has an 's' char prefix,391  // indicating that it is a string of hex values to be used as vector indices.392  bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1];393 394  bool HasRepeated = false;395  bool HasIndex[16] = {};396 397  int Idx;398 399  // Check that we've found one of the special components, or that the component400  // names must come from the same set.401  if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||402      !strcmp(compStr, "even") || !strcmp(compStr, "odd")) {403    HalvingSwizzle = true;404  } else if (!HexSwizzle &&405             (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {406    bool HasRGBA = IsRGBA(*compStr);407    do {408      // Ensure that xyzw and rgba components don't intermingle.409      if (HasRGBA != IsRGBA(*compStr))410        break;411      if (HasIndex[Idx]) HasRepeated = true;412      HasIndex[Idx] = true;413      compStr++;414    } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);415 416    // Emit a warning if an rgba selector is used earlier than OpenCL C 3.0.417    if (HasRGBA || (*compStr && IsRGBA(*compStr))) {418      if (S.getLangOpts().OpenCL &&419          S.getLangOpts().getOpenCLCompatibleVersion() < 300) {420        const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr;421        S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector)422            << StringRef(DiagBegin, 1) << SourceRange(CompLoc);423      }424    }425  } else {426    if (HexSwizzle) compStr++;427    while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {428      if (HasIndex[Idx]) HasRepeated = true;429      HasIndex[Idx] = true;430      compStr++;431    }432  }433 434  if (!HalvingSwizzle && *compStr) {435    // We didn't get to the end of the string. This means the component names436    // didn't come from the same set *or* we encountered an illegal name.437    size_t Offset = compStr - CompName->getNameStart() + 1;438    char Fmt[3] = {'\'', *compStr, '\''};439    S.Diag(OpLoc.getLocWithOffset(Offset),440           diag::err_ext_vector_component_name_illegal)441        << StringRef(Fmt, 3) << SourceRange(CompLoc);442    return QualType();443  }444 445  // Ensure no component accessor exceeds the width of the vector type it446  // operates on.447  if (!HalvingSwizzle) {448    compStr = CompName->getNameStart();449 450    if (HexSwizzle)451      compStr++;452 453    while (*compStr) {454      if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) {455        S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)456          << baseType << SourceRange(CompLoc);457        return QualType();458      }459    }460  }461 462  // OpenCL mode requires swizzle length to be in accordance with accepted463  // sizes. Clang however supports arbitrary lengths for other languages.464  if (S.getLangOpts().OpenCL && !HalvingSwizzle) {465    unsigned SwizzleLength = CompName->getLength();466 467    if (HexSwizzle)468      SwizzleLength--;469 470    if (IsValidOpenCLComponentSwizzleLength(SwizzleLength) == false) {471      S.Diag(OpLoc, diag::err_opencl_ext_vector_component_invalid_length)472        << SwizzleLength << SourceRange(CompLoc);473      return QualType();474    }475  }476 477  // The component accessor looks fine - now we need to compute the actual type.478  // The vector type is implied by the component accessor. For example,479  // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.480  // vec4.s0 is a float, vec4.s23 is a vec3, etc.481  // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.482  unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2483                                     : CompName->getLength();484  if (HexSwizzle)485    CompSize--;486 487  if (CompSize == 1)488    return vecType->getElementType();489 490  if (HasRepeated)491    VK = VK_PRValue;492 493  QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);494  // Now look up the TypeDefDecl from the vector type. Without this,495  // diagnostics look bad. We want extended vector types to appear built-in.496  for (Sema::ExtVectorDeclsType::iterator497         I = S.ExtVectorDecls.begin(S.getExternalSource()),498         E = S.ExtVectorDecls.end();499       I != E; ++I) {500    if ((*I)->getUnderlyingType() == VT)501      return S.Context.getTypedefType(ElaboratedTypeKeyword::None,502                                      /*Qualifier=*/std::nullopt, *I);503  }504 505  return VT; // should never get here (a typedef type should always be found).506}507 508static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,509                                                IdentifierInfo *Member,510                                                const Selector &Sel,511                                                ASTContext &Context) {512  if (Member)513    if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(514            Member, ObjCPropertyQueryKind::OBJC_PR_query_instance))515      return PD;516  if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))517    return OMD;518 519  for (const auto *I : PDecl->protocols()) {520    if (Decl *D = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel,521                                                           Context))522      return D;523  }524  return nullptr;525}526 527static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,528                                      IdentifierInfo *Member,529                                      const Selector &Sel,530                                      ASTContext &Context) {531  // Check protocols on qualified interfaces.532  Decl *GDecl = nullptr;533  for (const auto *I : QIdTy->quals()) {534    if (Member)535      if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(536              Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {537        GDecl = PD;538        break;539      }540    // Also must look for a getter or setter name which uses property syntax.541    if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) {542      GDecl = OMD;543      break;544    }545  }546  if (!GDecl) {547    for (const auto *I : QIdTy->quals()) {548      // Search in the protocol-qualifier list of current protocol.549      GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context);550      if (GDecl)551        return GDecl;552    }553  }554  return GDecl;555}556 557ExprResult558Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,559                               bool IsArrow, SourceLocation OpLoc,560                               const CXXScopeSpec &SS,561                               SourceLocation TemplateKWLoc,562                               NamedDecl *FirstQualifierInScope,563                               const DeclarationNameInfo &NameInfo,564                               const TemplateArgumentListInfo *TemplateArgs) {565  // Even in dependent contexts, try to diagnose base expressions with566  // obviously wrong types, e.g.:567  //568  // T* t;569  // t.f;570  //571  // In Obj-C++, however, the above expression is valid, since it could be572  // accessing the 'f' property if T is an Obj-C interface. The extra check573  // allows this, while still reporting an error if T is a struct pointer.574  if (!IsArrow) {575    const PointerType *PT = BaseType->getAs<PointerType>();576    if (PT && (!getLangOpts().ObjC ||577               PT->getPointeeType()->isRecordType())) {578      assert(BaseExpr && "cannot happen with implicit member accesses");579      Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)580        << BaseType << BaseExpr->getSourceRange() << NameInfo.getSourceRange();581      return ExprError();582    }583  }584 585  assert(BaseType->isDependentType() || NameInfo.getName().isDependentName() ||586         isDependentScopeSpecifier(SS) ||587         (TemplateArgs && llvm::any_of(TemplateArgs->arguments(),588                                       [](const TemplateArgumentLoc &Arg) {589                                         return Arg.getArgument().isDependent();590                                       })));591 592  // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr593  // must have pointer type, and the accessed type is the pointee.594  return CXXDependentScopeMemberExpr::Create(595      Context, BaseExpr, BaseType, IsArrow, OpLoc,596      SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope,597      NameInfo, TemplateArgs);598}599 600/// We know that the given qualified member reference points only to601/// declarations which do not belong to the static type of the base602/// expression.  Diagnose the problem.603static void DiagnoseQualifiedMemberReference(Sema &SemaRef,604                                             Expr *BaseExpr,605                                             QualType BaseType,606                                             const CXXScopeSpec &SS,607                                             NamedDecl *rep,608                                       const DeclarationNameInfo &nameInfo) {609  // If this is an implicit member access, use a different set of610  // diagnostics.611  if (!BaseExpr)612    return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo);613 614  SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)615    << SS.getRange() << rep << BaseType;616}617 618bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,619                                         QualType BaseType,620                                         const CXXScopeSpec &SS,621                                         const LookupResult &R) {622  CXXRecordDecl *BaseRecord =623    cast_or_null<CXXRecordDecl>(computeDeclContext(BaseType));624  if (!BaseRecord) {625    // We can't check this yet because the base type is still626    // dependent.627    assert(BaseType->isDependentType());628    return false;629  }630 631  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {632    // If this is an implicit member reference and we find a633    // non-instance member, it's not an error.634    if (!BaseExpr && !(*I)->isCXXInstanceMember())635      return false;636 637    // Note that we use the DC of the decl, not the underlying decl.638    DeclContext *DC = (*I)->getDeclContext()->getNonTransparentContext();639    if (!DC->isRecord())640      continue;641 642    CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl();643    if (BaseRecord->getCanonicalDecl() == MemberRecord ||644        !BaseRecord->isProvablyNotDerivedFrom(MemberRecord))645      return false;646  }647 648  DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS,649                                   R.getRepresentativeDecl(),650                                   R.getLookupNameInfo());651  return true;652}653 654static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,655                                     Expr *BaseExpr, QualType RTy,656                                     SourceLocation OpLoc, bool IsArrow,657                                     CXXScopeSpec &SS, bool HasTemplateArgs,658                                     SourceLocation TemplateKWLoc) {659  SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();660  if (!RTy->isDependentType() &&661      !SemaRef.isThisOutsideMemberFunctionBody(RTy) &&662      SemaRef.RequireCompleteType(663          OpLoc, RTy, diag::err_typecheck_incomplete_tag, BaseRange))664    return true;665 666  // LookupTemplateName/LookupParsedName don't expect these both to exist667  // simultaneously.668  QualType ObjectType = SS.isSet() ? QualType() : RTy;669  if (HasTemplateArgs || TemplateKWLoc.isValid())670    return SemaRef.LookupTemplateName(R,671                                      /*S=*/nullptr, SS, ObjectType,672                                      /*EnteringContext=*/false, TemplateKWLoc);673 674  SemaRef.LookupParsedName(R, /*S=*/nullptr, &SS, ObjectType);675  return false;676}677 678static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,679                                   ExprResult &BaseExpr, bool &IsArrow,680                                   SourceLocation OpLoc, CXXScopeSpec &SS,681                                   Decl *ObjCImpDecl, bool HasTemplateArgs,682                                   SourceLocation TemplateKWLoc);683 684ExprResult Sema::BuildMemberReferenceExpr(685    Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,686    CXXScopeSpec &SS, SourceLocation TemplateKWLoc,687    NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,688    const TemplateArgumentListInfo *TemplateArgs, const Scope *S,689    ActOnMemberAccessExtraArgs *ExtraArgs) {690  LookupResult R(*this, NameInfo, LookupMemberName);691 692  // Implicit member accesses.693  if (!Base) {694    QualType RecordTy = BaseType;695    if (IsArrow) RecordTy = RecordTy->castAs<PointerType>()->getPointeeType();696    if (LookupMemberExprInRecord(*this, R, nullptr, RecordTy, OpLoc, IsArrow,697                                 SS, TemplateArgs != nullptr, TemplateKWLoc))698      return ExprError();699 700  // Explicit member accesses.701  } else {702    ExprResult BaseResult = Base;703    ExprResult Result =704        LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS,705                         ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,706                         TemplateArgs != nullptr, TemplateKWLoc);707 708    if (BaseResult.isInvalid())709      return ExprError();710    Base = BaseResult.get();711 712    if (Result.isInvalid())713      return ExprError();714 715    if (Result.get())716      return Result;717 718    // LookupMemberExpr can modify Base, and thus change BaseType719    BaseType = Base->getType();720  }721 722  // BuildMemberReferenceExpr expects the nested-name-specifier, if any, to be723  // valid.724  if (SS.isInvalid())725    return ExprError();726 727  return BuildMemberReferenceExpr(Base, BaseType,728                                  OpLoc, IsArrow, SS, TemplateKWLoc,729                                  FirstQualifierInScope, R, TemplateArgs, S,730                                  false, ExtraArgs);731}732 733ExprResult734Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,735                                               SourceLocation loc,736                                               IndirectFieldDecl *indirectField,737                                               DeclAccessPair foundDecl,738                                               Expr *baseObjectExpr,739                                               SourceLocation opLoc) {740  // First, build the expression that refers to the base object.741 742  // Case 1:  the base of the indirect field is not a field.743  VarDecl *baseVariable = indirectField->getVarDecl();744  CXXScopeSpec EmptySS;745  if (baseVariable) {746    assert(baseVariable->getType()->isRecordType());747 748    // In principle we could have a member access expression that749    // accesses an anonymous struct/union that's a static member of750    // the base object's class.  However, under the current standard,751    // static data members cannot be anonymous structs or unions.752    // Supporting this is as easy as building a MemberExpr here.753    assert(!baseObjectExpr && "anonymous struct/union is static data member?");754 755    DeclarationNameInfo baseNameInfo(DeclarationName(), loc);756 757    ExprResult result758      = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);759    if (result.isInvalid()) return ExprError();760 761    baseObjectExpr = result.get();762  }763 764  assert((baseVariable || baseObjectExpr) &&765         "referencing anonymous struct/union without a base variable or "766         "expression");767 768  // Build the implicit member references to the field of the769  // anonymous struct/union.770  Expr *result = baseObjectExpr;771  IndirectFieldDecl::chain_iterator772  FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();773 774  // Case 2: the base of the indirect field is a field and the user775  // wrote a member expression.776  if (!baseVariable) {777    FieldDecl *field = cast<FieldDecl>(*FI);778 779    bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType();780 781    // Make a nameInfo that properly uses the anonymous name.782    DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);783 784    // Build the first member access in the chain with full information.785    result =786        BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(),787                                SS, field, foundDecl, memberNameInfo)788            .get();789    if (!result)790      return ExprError();791  }792 793  // In all cases, we should now skip the first declaration in the chain.794  ++FI;795 796  while (FI != FEnd) {797    FieldDecl *field = cast<FieldDecl>(*FI++);798 799    // FIXME: these are somewhat meaningless800    DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);801    DeclAccessPair fakeFoundDecl =802        DeclAccessPair::make(field, field->getAccess());803 804    result =805        BuildFieldReferenceExpr(result, /*isarrow*/ false, SourceLocation(),806                                (FI == FEnd ? SS : EmptySS), field,807                                fakeFoundDecl, memberNameInfo)808            .get();809  }810 811  return result;812}813 814static ExprResult815BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,816                       const CXXScopeSpec &SS,817                       MSPropertyDecl *PD,818                       const DeclarationNameInfo &NameInfo) {819  // Property names are always simple identifiers and therefore never820  // require any interesting additional storage.821  return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,822                                           S.Context.PseudoObjectTy, VK_LValue,823                                           SS.getWithLocInContext(S.Context),824                                           NameInfo.getLoc());825}826 827MemberExpr *Sema::BuildMemberExpr(828    Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS,829    SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,830    bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,831    QualType Ty, ExprValueKind VK, ExprObjectKind OK,832    const TemplateArgumentListInfo *TemplateArgs) {833  assert((!IsArrow || Base->isPRValue()) &&834         "-> base must be a pointer prvalue");835  MemberExpr *E =836      MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc,837                         Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty,838                         VK, OK, getNonOdrUseReasonInCurrentContext(Member));839  E->setHadMultipleCandidates(HadMultipleCandidates);840  MarkMemberReferenced(E);841 842  // C++ [except.spec]p17:843  //   An exception-specification is considered to be needed when:844  //   - in an expression the function is the unique lookup result or the845  //     selected member of a set of overloaded functions846  if (auto *FPT = Ty->getAs<FunctionProtoType>()) {847    if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {848      if (auto *NewFPT = ResolveExceptionSpec(MemberNameInfo.getLoc(), FPT))849        E->setType(Context.getQualifiedType(NewFPT, Ty.getQualifiers()));850    }851  }852 853  return E;854}855 856/// Determine if the given scope is within a function-try-block handler.857static bool IsInFnTryBlockHandler(const Scope *S) {858  // Walk the scope stack until finding a FnTryCatchScope, or leave the859  // function scope. If a FnTryCatchScope is found, check whether the TryScope860  // flag is set. If it is not, it's a function-try-block handler.861  for (; S != S->getFnParent(); S = S->getParent()) {862    if (S->isFnTryCatchScope())863      return (S->getFlags() & Scope::TryScope) != Scope::TryScope;864  }865  return false;866}867 868ExprResult869Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,870                               SourceLocation OpLoc, bool IsArrow,871                               const CXXScopeSpec &SS,872                               SourceLocation TemplateKWLoc,873                               NamedDecl *FirstQualifierInScope,874                               LookupResult &R,875                               const TemplateArgumentListInfo *TemplateArgs,876                               const Scope *S,877                               bool SuppressQualifierCheck,878                               ActOnMemberAccessExtraArgs *ExtraArgs) {879  assert(!SS.isInvalid() && "nested-name-specifier cannot be invalid");880  // If the member wasn't found in the current instantiation, or if the881  // arrow operator was used with a dependent non-pointer object expression,882  // build a CXXDependentScopeMemberExpr.883  if (R.wasNotFoundInCurrentInstantiation() ||884      (R.getLookupName().getCXXOverloadedOperator() == OO_Equal &&885       (SS.isSet() ? SS.getScopeRep().isDependent()886                   : BaseExprType->isDependentType())))887    return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS,888                                    TemplateKWLoc, FirstQualifierInScope,889                                    R.getLookupNameInfo(), TemplateArgs);890 891  QualType BaseType = BaseExprType;892  if (IsArrow) {893    assert(BaseType->isPointerType());894    BaseType = BaseType->castAs<PointerType>()->getPointeeType();895  }896  R.setBaseObjectType(BaseType);897 898  assert((SS.isEmpty()899              ? !BaseType->isDependentType() || computeDeclContext(BaseType)900              : !isDependentScopeSpecifier(SS) || computeDeclContext(SS)) &&901         "dependent lookup context that isn't the current instantiation?");902 903  const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();904  DeclarationName MemberName = MemberNameInfo.getName();905  SourceLocation MemberLoc = MemberNameInfo.getLoc();906 907  if (R.isAmbiguous())908    return ExprError();909 910  // [except.handle]p10: Referring to any non-static member or base class of an911  // object in the handler for a function-try-block of a constructor or912  // destructor for that object results in undefined behavior.913  const auto *FD = getCurFunctionDecl();914  if (S && BaseExpr && FD &&915      (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&916      isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) &&917      IsInFnTryBlockHandler(S))918    Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr)919        << isa<CXXDestructorDecl>(FD);920 921  if (R.empty()) {922    ExprResult RetryExpr = ExprError();923    if (ExtraArgs && !IsArrow && BaseExpr && !BaseExpr->isTypeDependent()) {924      SFINAETrap Trap(*this, true);925      ParsedType ObjectType;926      bool MayBePseudoDestructor = false;927      RetryExpr = ActOnStartCXXMemberReference(getCurScope(), BaseExpr, OpLoc,928                                               tok::arrow, ObjectType,929                                               MayBePseudoDestructor);930      if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {931        CXXScopeSpec TempSS(SS);932        RetryExpr = ActOnMemberAccessExpr(933            ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,934            TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);935      }936      if (Trap.hasErrorOccurred())937        RetryExpr = ExprError();938    }939 940    // Rederive where we looked up.941    DeclContext *DC =942        (SS.isSet() ? computeDeclContext(SS) : computeDeclContext(BaseType));943    assert(DC);944 945    if (RetryExpr.isUsable())946      Diag(OpLoc, diag::err_no_member_overloaded_arrow)947          << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->");948    else949      Diag(R.getNameLoc(), diag::err_no_member)950          << MemberName << DC951          << (SS.isSet()952                  ? SS.getRange()953                  : (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()));954    return RetryExpr;955  }956 957  // Diagnose lookups that find only declarations from a non-base958  // type.  This is possible for either qualified lookups (which may959  // have been qualified with an unrelated type) or implicit member960  // expressions (which were found with unqualified lookup and thus961  // may have come from an enclosing scope).  Note that it's okay for962  // lookup to find declarations from a non-base type as long as those963  // aren't the ones picked by overload resolution.964  if ((SS.isSet() || !BaseExpr ||965       (isa<CXXThisExpr>(BaseExpr) &&966        cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&967      !SuppressQualifierCheck &&968      CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))969    return ExprError();970 971  // Construct an unresolved result if we in fact got an unresolved972  // result.973  if (R.isOverloadedResult() || R.isUnresolvableResult()) {974    // Suppress any lookup-related diagnostics; we'll do these when we975    // pick a member.976    R.suppressDiagnostics();977 978    UnresolvedMemberExpr *MemExpr979      = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(),980                                     BaseExpr, BaseExprType,981                                     IsArrow, OpLoc,982                                     SS.getWithLocInContext(Context),983                                     TemplateKWLoc, MemberNameInfo,984                                     TemplateArgs, R.begin(), R.end());985 986    return MemExpr;987  }988 989  assert(R.isSingleResult());990  DeclAccessPair FoundDecl = R.begin().getPair();991  NamedDecl *MemberDecl = R.getFoundDecl();992 993  // FIXME: diagnose the presence of template arguments now.994 995  // If the decl being referenced had an error, return an error for this996  // sub-expr without emitting another error, in order to avoid cascading997  // error cases.998  if (MemberDecl->isInvalidDecl())999    return ExprError();1000 1001  // Handle the implicit-member-access case.1002  if (!BaseExpr) {1003    // If this is not an instance member, convert to a non-member access.1004    if (!MemberDecl->isCXXInstanceMember()) {1005      // We might have a variable template specialization (or maybe one day a1006      // member concept-id).1007      if (TemplateArgs || TemplateKWLoc.isValid())1008        return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/false, TemplateArgs);1009 1010      return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl,1011                                      FoundDecl, TemplateArgs);1012    }1013    SourceLocation Loc = R.getNameLoc();1014    if (SS.getRange().isValid())1015      Loc = SS.getRange().getBegin();1016    BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true);1017  }1018 1019  // C++17 [expr.ref]p2, per CWG2813:1020  //   For the first option (dot), if the id-expression names a static member or1021  //   an enumerator, the first expression is a discarded-value expression; if1022  //   the id-expression names a non-static data member, the first expression1023  //   shall be a glvalue.1024  auto ConvertBaseExprToDiscardedValue = [&] {1025    assert(getLangOpts().CPlusPlus &&1026           "Static member / member enumerator outside of C++");1027    if (IsArrow)1028      return false;1029    ExprResult Converted = IgnoredValueConversions(BaseExpr);1030    if (Converted.isInvalid())1031      return true;1032    BaseExpr = Converted.get();1033    return false;1034  };1035  auto ConvertBaseExprToGLValue = [&] {1036    if (IsArrow || !BaseExpr->isPRValue())1037      return false;1038    ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);1039    if (Converted.isInvalid())1040      return true;1041    BaseExpr = Converted.get();1042    return false;1043  };1044 1045  // Check the use of this member.1046  if (DiagnoseUseOfDecl(MemberDecl, MemberLoc))1047    return ExprError();1048 1049  if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {1050    if (ConvertBaseExprToGLValue())1051      return ExprError();1052    return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl,1053                                   MemberNameInfo);1054  }1055 1056  if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl)) {1057    // No temporaries are materialized for property references yet.1058    // They might be materialized when this is transformed into a member call.1059    // Note that this is slightly different behaviour from MSVC which doesn't1060    // implement CWG2813 yet: MSVC might materialize an extra temporary if the1061    // getter or setter function is an explicit object member function.1062    return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,1063                                  MemberNameInfo);1064  }1065 1066  if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) {1067    if (ConvertBaseExprToGLValue())1068      return ExprError();1069    // We may have found a field within an anonymous union or struct1070    // (C++ [class.union]).1071    return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,1072                                                    FoundDecl, BaseExpr,1073                                                    OpLoc);1074  }1075 1076  // Static data member1077  if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {1078    if (ConvertBaseExprToDiscardedValue())1079      return ExprError();1080    return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,1081                           SS.getWithLocInContext(Context), TemplateKWLoc, Var,1082                           FoundDecl, /*HadMultipleCandidates=*/false,1083                           MemberNameInfo, Var->getType().getNonReferenceType(),1084                           VK_LValue, OK_Ordinary);1085  }1086 1087  if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {1088    ExprValueKind valueKind;1089    QualType type;1090    if (MemberFn->isInstance()) {1091      valueKind = VK_PRValue;1092      type = Context.BoundMemberTy;1093      if (MemberFn->isImplicitObjectMemberFunction() &&1094          ConvertBaseExprToGLValue())1095        return ExprError();1096    } else {1097      // Static member function1098      if (ConvertBaseExprToDiscardedValue())1099        return ExprError();1100      valueKind = VK_LValue;1101      type = MemberFn->getType();1102    }1103 1104    return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,1105                           SS.getWithLocInContext(Context), TemplateKWLoc,1106                           MemberFn, FoundDecl, /*HadMultipleCandidates=*/false,1107                           MemberNameInfo, type, valueKind, OK_Ordinary);1108  }1109  assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");1110 1111  if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {1112    if (ConvertBaseExprToDiscardedValue())1113      return ExprError();1114    return BuildMemberExpr(1115        BaseExpr, IsArrow, OpLoc, SS.getWithLocInContext(Context),1116        TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandidates=*/false,1117        MemberNameInfo, Enum->getType(), VK_PRValue, OK_Ordinary);1118  }1119 1120  if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {1121    if (ConvertBaseExprToDiscardedValue())1122      return ExprError();1123    if (!TemplateArgs) {1124      diagnoseMissingTemplateArguments(1125          SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc);1126      return ExprError();1127    }1128 1129    DeclResult VDecl =1130        CheckVarTemplateId(VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(),1131                           *TemplateArgs, /*SetWrittenArgs=*/false);1132    if (VDecl.isInvalid())1133      return ExprError();1134 1135    // Non-dependent member, but dependent template arguments.1136    if (!VDecl.get())1137      return ActOnDependentMemberExpr(1138          BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc,1139          FirstQualifierInScope, MemberNameInfo, TemplateArgs);1140 1141    VarDecl *Var = cast<VarDecl>(VDecl.get());1142    if (!Var->getTemplateSpecializationKind())1143      Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc);1144 1145    return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,1146                           SS.getWithLocInContext(Context), TemplateKWLoc, Var,1147                           FoundDecl, /*HadMultipleCandidates=*/false,1148                           MemberNameInfo, Var->getType().getNonReferenceType(),1149                           VK_LValue, OK_Ordinary, TemplateArgs);1150  }1151 1152  // We found something that we didn't expect. Complain.1153  if (isa<TypeDecl>(MemberDecl))1154    Diag(MemberLoc, diag::err_typecheck_member_reference_type)1155      << MemberName << BaseType << int(IsArrow);1156  else1157    Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)1158      << MemberName << BaseType << int(IsArrow);1159 1160  Diag(MemberDecl->getLocation(), diag::note_member_declared_here)1161    << MemberName;1162  R.suppressDiagnostics();1163  return ExprError();1164}1165 1166/// Given that normal member access failed on the given expression,1167/// and given that the expression's type involves builtin-id or1168/// builtin-Class, decide whether substituting in the redefinition1169/// types would be profitable.  The redefinition type is whatever1170/// this translation unit tried to typedef to id/Class;  we store1171/// it to the side and then re-use it in places like this.1172static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) {1173  const ObjCObjectPointerType *opty1174    = base.get()->getType()->getAs<ObjCObjectPointerType>();1175  if (!opty) return false;1176 1177  const ObjCObjectType *ty = opty->getObjectType();1178 1179  QualType redef;1180  if (ty->isObjCId()) {1181    redef = S.Context.getObjCIdRedefinitionType();1182  } else if (ty->isObjCClass()) {1183    redef = S.Context.getObjCClassRedefinitionType();1184  } else {1185    return false;1186  }1187 1188  // Do the substitution as long as the redefinition type isn't just a1189  // possibly-qualified pointer to builtin-id or builtin-Class again.1190  opty = redef->getAs<ObjCObjectPointerType>();1191  if (opty && !opty->getObjectType()->getInterface())1192    return false;1193 1194  base = S.ImpCastExprToType(base.get(), redef, CK_BitCast);1195  return true;1196}1197 1198static bool isRecordType(QualType T) {1199  return T->isRecordType();1200}1201static bool isPointerToRecordType(QualType T) {1202  if (const PointerType *PT = T->getAs<PointerType>())1203    return PT->getPointeeType()->isRecordType();1204  return false;1205}1206 1207ExprResult1208Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {1209  if (IsArrow && !Base->getType()->isFunctionType())1210    return DefaultFunctionArrayLvalueConversion(Base);1211 1212  return CheckPlaceholderExpr(Base);1213}1214 1215/// Look up the given member of the given non-type-dependent1216/// expression.  This can return in one of two ways:1217///  * If it returns a sentinel null-but-valid result, the caller will1218///    assume that lookup was performed and the results written into1219///    the provided structure.  It will take over from there.1220///  * Otherwise, the returned expression will be produced in place of1221///    an ordinary member expression.1222///1223/// The ObjCImpDecl bit is a gross hack that will need to be properly1224/// fixed for ObjC++.1225static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,1226                                   ExprResult &BaseExpr, bool &IsArrow,1227                                   SourceLocation OpLoc, CXXScopeSpec &SS,1228                                   Decl *ObjCImpDecl, bool HasTemplateArgs,1229                                   SourceLocation TemplateKWLoc) {1230  assert(BaseExpr.get() && "no base expression");1231 1232  // Perform default conversions.1233  BaseExpr = S.PerformMemberExprBaseConversion(BaseExpr.get(), IsArrow);1234  if (BaseExpr.isInvalid())1235    return ExprError();1236 1237  QualType BaseType = BaseExpr.get()->getType();1238 1239  DeclarationName MemberName = R.getLookupName();1240  SourceLocation MemberLoc = R.getNameLoc();1241 1242  // For later type-checking purposes, turn arrow accesses into dot1243  // accesses.  The only access type we support that doesn't follow1244  // the C equivalence "a->b === (*a).b" is ObjC property accesses,1245  // and those never use arrows, so this is unaffected.1246  if (IsArrow) {1247    if (const PointerType *Ptr = BaseType->getAs<PointerType>())1248      BaseType = Ptr->getPointeeType();1249    else if (const ObjCObjectPointerType *Ptr =1250                 BaseType->getAs<ObjCObjectPointerType>())1251      BaseType = Ptr->getPointeeType();1252    else if (BaseType->isFunctionType())1253      goto fail;1254    else if (BaseType->isDependentType())1255      BaseType = S.Context.DependentTy;1256    else if (BaseType->isRecordType()) {1257      // Recover from arrow accesses to records, e.g.:1258      //   struct MyRecord foo;1259      //   foo->bar1260      // This is actually well-formed in C++ if MyRecord has an1261      // overloaded operator->, but that should have been dealt with1262      // by now--or a diagnostic message already issued if a problem1263      // was encountered while looking for the overloaded operator->.1264      if (!S.getLangOpts().CPlusPlus) {1265        S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)1266            << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()1267            << FixItHint::CreateReplacement(OpLoc, ".");1268      }1269      IsArrow = false;1270    } else {1271      S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)1272          << BaseType << BaseExpr.get()->getSourceRange();1273      return ExprError();1274    }1275  }1276 1277  // If the base type is an atomic type, this access is undefined behavior per1278  // C11 6.5.2.3p5. Instead of giving a typecheck error, we'll warn the user1279  // about the UB and recover by converting the atomic lvalue into a non-atomic1280  // lvalue. Because this is inherently unsafe as an atomic operation, the1281  // warning defaults to an error.1282  if (const auto *ATy = BaseType->getAs<AtomicType>()) {1283    S.DiagRuntimeBehavior(OpLoc, BaseExpr.get(),1284                          S.PDiag(diag::warn_atomic_member_access));1285    BaseType = ATy->getValueType().getUnqualifiedType();1286    BaseExpr = ImplicitCastExpr::Create(1287        S.Context, IsArrow ? S.Context.getPointerType(BaseType) : BaseType,1288        CK_AtomicToNonAtomic, BaseExpr.get(), nullptr,1289        BaseExpr.get()->getValueKind(), FPOptionsOverride());1290  }1291 1292  // Handle field access to simple records.1293  if (BaseType->getAsRecordDecl()) {1294    if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow,1295                                 SS, HasTemplateArgs, TemplateKWLoc))1296      return ExprError();1297 1298    // Returning valid-but-null is how we indicate to the caller that1299    // the lookup result was filled in. If typo correction was attempted and1300    // failed, the lookup result will have been cleared--that combined with the1301    // valid-but-null ExprResult will trigger the appropriate diagnostics.1302    return ExprResult{};1303  } else if (BaseType->isDependentType()) {1304    R.setNotFoundInCurrentInstantiation();1305    return ExprEmpty();1306  }1307 1308  // Handle ivar access to Objective-C objects.1309  if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) {1310    if (!SS.isEmpty() && !SS.isInvalid()) {1311      S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)1312        << 1 << SS.getScopeRep()1313        << FixItHint::CreateRemoval(SS.getRange());1314      SS.clear();1315    }1316 1317    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();1318 1319    // There are three cases for the base type:1320    //   - builtin id (qualified or unqualified)1321    //   - builtin Class (qualified or unqualified)1322    //   - an interface1323    ObjCInterfaceDecl *IDecl = OTy->getInterface();1324    if (!IDecl) {1325      if (S.getLangOpts().ObjCAutoRefCount &&1326          (OTy->isObjCId() || OTy->isObjCClass()))1327        goto fail;1328      // There's an implicit 'isa' ivar on all objects.1329      // But we only actually find it this way on objects of type 'id',1330      // apparently.1331      if (OTy->isObjCId() && Member->isStr("isa"))1332        return new (S.Context) ObjCIsaExpr(BaseExpr.get(), IsArrow, MemberLoc,1333                                           OpLoc, S.Context.getObjCClassType());1334      if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))1335        return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1336                                ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1337      goto fail;1338    }1339 1340    if (S.RequireCompleteType(OpLoc, BaseType,1341                              diag::err_typecheck_incomplete_tag,1342                              BaseExpr.get()))1343      return ExprError();1344 1345    ObjCInterfaceDecl *ClassDeclared = nullptr;1346    ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);1347 1348    if (!IV) {1349      // Attempt to correct for typos in ivar names.1350      DeclFilterCCC<ObjCIvarDecl> Validator{};1351      Validator.IsObjCIvarLookup = IsArrow;1352      if (TypoCorrection Corrected = S.CorrectTypo(1353              R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,1354              Validator, CorrectTypoKind::ErrorRecovery, IDecl)) {1355        IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();1356        S.diagnoseTypo(1357            Corrected,1358            S.PDiag(diag::err_typecheck_member_reference_ivar_suggest)1359                << IDecl->getDeclName() << MemberName);1360 1361        // Figure out the class that declares the ivar.1362        assert(!ClassDeclared);1363 1364        Decl *D = cast<Decl>(IV->getDeclContext());1365        if (auto *Category = dyn_cast<ObjCCategoryDecl>(D))1366          D = Category->getClassInterface();1367 1368        if (auto *Implementation = dyn_cast<ObjCImplementationDecl>(D))1369          ClassDeclared = Implementation->getClassInterface();1370        else if (auto *Interface = dyn_cast<ObjCInterfaceDecl>(D))1371          ClassDeclared = Interface;1372 1373        assert(ClassDeclared && "cannot query interface");1374      } else {1375        if (IsArrow &&1376            IDecl->FindPropertyDeclaration(1377                Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {1378          S.Diag(MemberLoc, diag::err_property_found_suggest)1379              << Member << BaseExpr.get()->getType()1380              << FixItHint::CreateReplacement(OpLoc, ".");1381          return ExprError();1382        }1383 1384        S.Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)1385            << IDecl->getDeclName() << MemberName1386            << BaseExpr.get()->getSourceRange();1387        return ExprError();1388      }1389    }1390 1391    assert(ClassDeclared);1392 1393    // If the decl being referenced had an error, return an error for this1394    // sub-expr without emitting another error, in order to avoid cascading1395    // error cases.1396    if (IV->isInvalidDecl())1397      return ExprError();1398 1399    // Check whether we can reference this field.1400    if (S.DiagnoseUseOfDecl(IV, MemberLoc))1401      return ExprError();1402    if (IV->getAccessControl() != ObjCIvarDecl::Public &&1403        IV->getAccessControl() != ObjCIvarDecl::Package) {1404      ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;1405      if (ObjCMethodDecl *MD = S.getCurMethodDecl())1406        ClassOfMethodDecl =  MD->getClassInterface();1407      else if (ObjCImpDecl && S.getCurFunctionDecl()) {1408        // Case of a c-function declared inside an objc implementation.1409        // FIXME: For a c-style function nested inside an objc implementation1410        // class, there is no implementation context available, so we pass1411        // down the context as argument to this routine. Ideally, this context1412        // need be passed down in the AST node and somehow calculated from the1413        // AST for a function decl.1414        if (ObjCImplementationDecl *IMPD =1415              dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))1416          ClassOfMethodDecl = IMPD->getClassInterface();1417        else if (ObjCCategoryImplDecl* CatImplClass =1418                   dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl))1419          ClassOfMethodDecl = CatImplClass->getClassInterface();1420      }1421      if (!S.getLangOpts().DebuggerSupport) {1422        if (IV->getAccessControl() == ObjCIvarDecl::Private) {1423          if (!declaresSameEntity(ClassDeclared, IDecl) ||1424              !declaresSameEntity(ClassOfMethodDecl, ClassDeclared))1425            S.Diag(MemberLoc, diag::err_private_ivar_access)1426              << IV->getDeclName();1427        } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))1428          // @protected1429          S.Diag(MemberLoc, diag::err_protected_ivar_access)1430              << IV->getDeclName();1431      }1432    }1433    bool warn = true;1434    if (S.getLangOpts().ObjCWeak) {1435      Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts();1436      if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp))1437        if (UO->getOpcode() == UO_Deref)1438          BaseExp = UO->getSubExpr()->IgnoreParenCasts();1439 1440      if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp))1441        if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {1442          S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access);1443          warn = false;1444        }1445    }1446    if (warn) {1447      if (ObjCMethodDecl *MD = S.getCurMethodDecl()) {1448        ObjCMethodFamily MF = MD->getMethodFamily();1449        warn = (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&1450                !S.ObjC().IvarBacksCurrentMethodAccessor(IDecl, MD, IV));1451      }1452      if (warn)1453        S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();1454    }1455 1456    ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr(1457        IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(),1458        IsArrow);1459 1460    if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {1461      if (!S.isUnevaluatedContext() &&1462          !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))1463        S.getCurFunction()->recordUseOfWeak(Result);1464    }1465 1466    return Result;1467  }1468 1469  // Objective-C property access.1470  const ObjCObjectPointerType *OPT;1471  if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {1472    if (!SS.isEmpty() && !SS.isInvalid()) {1473      S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)1474          << 0 << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());1475      SS.clear();1476    }1477 1478    // This actually uses the base as an r-value.1479    BaseExpr = S.DefaultLvalueConversion(BaseExpr.get());1480    if (BaseExpr.isInvalid())1481      return ExprError();1482 1483    assert(S.Context.hasSameUnqualifiedType(BaseType,1484                                            BaseExpr.get()->getType()));1485 1486    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();1487 1488    const ObjCObjectType *OT = OPT->getObjectType();1489 1490    // id, with and without qualifiers.1491    if (OT->isObjCId()) {1492      // Check protocols on qualified interfaces.1493      Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);1494      if (Decl *PMDecl =1495              FindGetterSetterNameDecl(OPT, Member, Sel, S.Context)) {1496        if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {1497          // Check the use of this declaration1498          if (S.DiagnoseUseOfDecl(PD, MemberLoc))1499            return ExprError();1500 1501          return new (S.Context)1502              ObjCPropertyRefExpr(PD, S.Context.PseudoObjectTy, VK_LValue,1503                                  OK_ObjCProperty, MemberLoc, BaseExpr.get());1504        }1505 1506        if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {1507          Selector SetterSel =1508            SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),1509                                                   S.PP.getSelectorTable(),1510                                                   Member);1511          ObjCMethodDecl *SMD = nullptr;1512          if (Decl *SDecl = FindGetterSetterNameDecl(OPT,1513                                                     /*Property id*/ nullptr,1514                                                     SetterSel, S.Context))1515            SMD = dyn_cast<ObjCMethodDecl>(SDecl);1516 1517          return new (S.Context)1518              ObjCPropertyRefExpr(OMD, SMD, S.Context.PseudoObjectTy, VK_LValue,1519                                  OK_ObjCProperty, MemberLoc, BaseExpr.get());1520        }1521      }1522      // Use of id.member can only be for a property reference. Do not1523      // use the 'id' redefinition in this case.1524      if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr))1525        return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1526                                ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1527 1528      return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)1529                         << MemberName << BaseType);1530    }1531 1532    // 'Class', unqualified only.1533    if (OT->isObjCClass()) {1534      // Only works in a method declaration (??!).1535      ObjCMethodDecl *MD = S.getCurMethodDecl();1536      if (!MD) {1537        if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))1538          return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1539                                  ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1540 1541        goto fail;1542      }1543 1544      // Also must look for a getter name which uses property syntax.1545      Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);1546      ObjCInterfaceDecl *IFace = MD->getClassInterface();1547      if (!IFace)1548        goto fail;1549 1550      ObjCMethodDecl *Getter;1551      if ((Getter = IFace->lookupClassMethod(Sel))) {1552        // Check the use of this method.1553        if (S.DiagnoseUseOfDecl(Getter, MemberLoc))1554          return ExprError();1555      } else1556        Getter = IFace->lookupPrivateMethod(Sel, false);1557      // If we found a getter then this may be a valid dot-reference, we1558      // will look for the matching setter, in case it is needed.1559      Selector SetterSel =1560        SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),1561                                               S.PP.getSelectorTable(),1562                                               Member);1563      ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);1564      if (!Setter) {1565        // If this reference is in an @implementation, also check for 'private'1566        // methods.1567        Setter = IFace->lookupPrivateMethod(SetterSel, false);1568      }1569 1570      if (Setter && S.DiagnoseUseOfDecl(Setter, MemberLoc))1571        return ExprError();1572 1573      if (Getter || Setter) {1574        return new (S.Context) ObjCPropertyRefExpr(1575            Getter, Setter, S.Context.PseudoObjectTy, VK_LValue,1576            OK_ObjCProperty, MemberLoc, BaseExpr.get());1577      }1578 1579      if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))1580        return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1581                                ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1582 1583      return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)1584                         << MemberName << BaseType);1585    }1586 1587    // Normal property access.1588    return S.ObjC().HandleExprPropertyRefExpr(1589        OPT, BaseExpr.get(), OpLoc, MemberName, MemberLoc, SourceLocation(),1590        QualType(), false);1591  }1592 1593  if (BaseType->isPackedVectorBoolType(S.Context)) {1594    // We disallow element access for ext_vector_type bool.  There is no way to1595    // materialize a reference to a vector element as a pointer (each element is1596    // one bit in the vector).1597    S.Diag(R.getNameLoc(), diag::err_ext_vector_component_name_illegal)1598        << MemberName1599        << (BaseExpr.get() ? BaseExpr.get()->getSourceRange() : SourceRange());1600    return ExprError();1601  }1602 1603  // Handle 'field access' to vectors, such as 'V.xx'.1604  if (BaseType->isExtVectorType()) {1605    // FIXME: this expr should store IsArrow.1606    IdentifierInfo *Member = MemberName.getAsIdentifierInfo();1607    ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());1608    QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,1609                                           Member, MemberLoc);1610    if (ret.isNull())1611      return ExprError();1612    Qualifiers BaseQ =1613        S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers();1614    ret = S.Context.getQualifiedType(ret, BaseQ);1615 1616    return new (S.Context)1617        ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc);1618  }1619 1620  // Adjust builtin-sel to the appropriate redefinition type if that's1621  // not just a pointer to builtin-sel again.1622  if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&1623      !S.Context.getObjCSelRedefinitionType()->isObjCSelType()) {1624    BaseExpr = S.ImpCastExprToType(1625        BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast);1626    return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1627                            ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1628  }1629 1630  // Failure cases.1631 fail:1632 1633  // Recover from dot accesses to pointers, e.g.:1634  //   type *foo;1635  //   foo.bar1636  // This is actually well-formed in two cases:1637  //   - 'type' is an Objective C type1638  //   - 'bar' is a pseudo-destructor name which happens to refer to1639  //     the appropriate pointer type1640  if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {1641    if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&1642        MemberName.getNameKind() != DeclarationName::CXXDestructorName) {1643      S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)1644          << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()1645          << FixItHint::CreateReplacement(OpLoc, "->");1646 1647      if (S.isSFINAEContext())1648        return ExprError();1649 1650      // Recurse as an -> access.1651      IsArrow = true;1652      return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1653                              ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1654    }1655  }1656 1657  // If the user is trying to apply -> or . to a function name, it's probably1658  // because they forgot parentheses to call that function.1659  if (S.tryToRecoverWithCall(1660          BaseExpr, S.PDiag(diag::err_member_reference_needs_call),1661          /*complain*/ false,1662          IsArrow ? &isPointerToRecordType : &isRecordType)) {1663    if (BaseExpr.isInvalid())1664      return ExprError();1665    BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get());1666    return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1667                            ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1668  }1669 1670  // HLSL supports implicit conversion of scalar types to single element vector1671  // rvalues in member expressions.1672  if (S.getLangOpts().HLSL && BaseType->isScalarType()) {1673    QualType VectorTy = S.Context.getExtVectorType(BaseType, 1);1674    BaseExpr = S.ImpCastExprToType(BaseExpr.get(), VectorTy, CK_VectorSplat,1675                                   BaseExpr.get()->getValueKind());1676    return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl,1677                            HasTemplateArgs, TemplateKWLoc);1678  }1679 1680  S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)1681    << BaseType << BaseExpr.get()->getSourceRange() << MemberLoc;1682 1683  return ExprError();1684}1685 1686ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,1687                                       SourceLocation OpLoc,1688                                       tok::TokenKind OpKind, CXXScopeSpec &SS,1689                                       SourceLocation TemplateKWLoc,1690                                       UnqualifiedId &Id, Decl *ObjCImpDecl) {1691  // Warn about the explicit constructor calls Microsoft extension.1692  if (getLangOpts().MicrosoftExt &&1693      Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)1694    Diag(Id.getSourceRange().getBegin(),1695         diag::ext_ms_explicit_constructor_call);1696 1697  TemplateArgumentListInfo TemplateArgsBuffer;1698 1699  // Decompose the name into its component parts.1700  DeclarationNameInfo NameInfo;1701  const TemplateArgumentListInfo *TemplateArgs;1702  DecomposeUnqualifiedId(Id, TemplateArgsBuffer,1703                         NameInfo, TemplateArgs);1704 1705  bool IsArrow = (OpKind == tok::arrow);1706 1707  if (getLangOpts().HLSL && IsArrow)1708    return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2);1709 1710  NamedDecl *FirstQualifierInScope1711    = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep()));1712 1713  // This is a postfix expression, so get rid of ParenListExprs.1714  ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);1715  if (Result.isInvalid()) return ExprError();1716  Base = Result.get();1717 1718  ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};1719  ExprResult Res = BuildMemberReferenceExpr(1720      Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc,1721      FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs);1722 1723  if (!Res.isInvalid() && isa<MemberExpr>(Res.get()))1724    CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get()));1725 1726  return Res;1727}1728 1729void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {1730  if (isUnevaluatedContext())1731    return;1732 1733  QualType ResultTy = E->getType();1734 1735  // Member accesses have four cases:1736  // 1: non-array member via "->": dereferences1737  // 2: non-array member via ".": nothing interesting happens1738  // 3: array member access via "->": nothing interesting happens1739  //    (this returns an array lvalue and does not actually dereference memory)1740  // 4: array member access via ".": *adds* a layer of indirection1741  if (ResultTy->isArrayType()) {1742    if (!E->isArrow()) {1743      // This might be something like:1744      //     (*structPtr).arrayMember1745      // which behaves roughly like:1746      //     &(*structPtr).pointerMember1747      // in that the apparent dereference in the base expression does not1748      // actually happen.1749      CheckAddressOfNoDeref(E->getBase());1750    }1751  } else if (E->isArrow()) {1752    if (const auto *Ptr = dyn_cast<PointerType>(1753            E->getBase()->getType().getDesugaredType(Context))) {1754      if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))1755        ExprEvalContexts.back().PossibleDerefs.insert(E);1756    }1757  }1758}1759 1760ExprResult1761Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,1762                              SourceLocation OpLoc, const CXXScopeSpec &SS,1763                              FieldDecl *Field, DeclAccessPair FoundDecl,1764                              const DeclarationNameInfo &MemberNameInfo) {1765  // x.a is an l-value if 'a' has a reference type. Otherwise:1766  // x.a is an l-value/x-value/pr-value if the base is (and note1767  //   that *x is always an l-value), except that if the base isn't1768  //   an ordinary object then we must have an rvalue.1769  ExprValueKind VK = VK_LValue;1770  ExprObjectKind OK = OK_Ordinary;1771  if (!IsArrow) {1772    if (BaseExpr->getObjectKind() == OK_Ordinary)1773      VK = BaseExpr->getValueKind();1774    else1775      VK = VK_PRValue;1776  }1777  if (VK != VK_PRValue && Field->isBitField())1778    OK = OK_BitField;1779 1780  // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]1781  QualType MemberType = Field->getType();1782  if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {1783    MemberType = Ref->getPointeeType();1784    VK = VK_LValue;1785  } else {1786    QualType BaseType = BaseExpr->getType();1787    if (IsArrow) BaseType = BaseType->castAs<PointerType>()->getPointeeType();1788 1789    Qualifiers BaseQuals = BaseType.getQualifiers();1790 1791    // GC attributes are never picked up by members.1792    BaseQuals.removeObjCGCAttr();1793 1794    // CVR attributes from the base are picked up by members,1795    // except that 'mutable' members don't pick up 'const'.1796    if (Field->isMutable()) BaseQuals.removeConst();1797 1798    Qualifiers MemberQuals =1799        Context.getCanonicalType(MemberType).getQualifiers();1800 1801    assert(!MemberQuals.hasAddressSpace());1802 1803    Qualifiers Combined = BaseQuals + MemberQuals;1804    if (Combined != MemberQuals)1805      MemberType = Context.getQualifiedType(MemberType, Combined);1806 1807    // Pick up NoDeref from the base in case we end up using AddrOf on the1808    // result. E.g. the expression1809    //     &someNoDerefPtr->pointerMember1810    // should be a noderef pointer again.1811    if (BaseType->hasAttr(attr::NoDeref))1812      MemberType =1813          Context.getAttributedType(attr::NoDeref, MemberType, MemberType);1814  }1815 1816  auto isDefaultedSpecialMember = [this](const DeclContext *Ctx) {1817    auto *Method = dyn_cast<CXXMethodDecl>(CurContext);1818    if (!Method || !Method->isDefaulted())1819      return false;1820 1821    return getDefaultedFunctionKind(Method).isSpecialMember();1822  };1823 1824  // Implicit special members should not mark fields as used.1825  if (!isDefaultedSpecialMember(CurContext))1826    UnusedPrivateFields.remove(Field);1827 1828  ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),1829                                                  FoundDecl, Field);1830  if (Base.isInvalid())1831    return ExprError();1832 1833  // Build a reference to a private copy for non-static data members in1834  // non-static member functions, privatized by OpenMP constructs.1835  if (getLangOpts().OpenMP && IsArrow &&1836      !CurContext->isDependentContext() &&1837      isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {1838    if (auto *PrivateCopy = OpenMP().isOpenMPCapturedDecl(Field)) {1839      return OpenMP().getOpenMPCapturedExpr(PrivateCopy, VK, OK,1840                                            MemberNameInfo.getLoc());1841    }1842  }1843 1844  return BuildMemberExpr(1845      Base.get(), IsArrow, OpLoc, SS.getWithLocInContext(Context),1846      /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,1847      /*HadMultipleCandidates=*/false, MemberNameInfo, MemberType, VK, OK);1848}1849 1850ExprResult1851Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,1852                              SourceLocation TemplateKWLoc,1853                              LookupResult &R,1854                              const TemplateArgumentListInfo *TemplateArgs,1855                              bool IsKnownInstance, const Scope *S) {1856  assert(!R.empty() && !R.isAmbiguous());1857 1858  SourceLocation loc = R.getNameLoc();1859 1860  // If this is known to be an instance access, go ahead and build an1861  // implicit 'this' expression now.1862  QualType ThisTy = getCurrentThisType();1863  assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");1864 1865  Expr *baseExpr = nullptr; // null signifies implicit access1866  if (IsKnownInstance) {1867    SourceLocation Loc = R.getNameLoc();1868    if (SS.getRange().isValid())1869      Loc = SS.getRange().getBegin();1870    baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true);1871  }1872 1873  return BuildMemberReferenceExpr(1874      baseExpr, ThisTy,1875      /*OpLoc=*/SourceLocation(),1876      /*IsArrow=*/!getLangOpts().HLSL, SS, TemplateKWLoc,1877      /*FirstQualifierInScope=*/nullptr, R, TemplateArgs, S);1878}1879