xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaExprMember.cpp (revision 62987288060ff68c817b7056815aa9fb8ba8ecd7)
10b57cec5SDimitry Andric //===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file implements semantic analysis member access expressions.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric #include "clang/AST/ASTLambda.h"
130b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
140b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
150b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
160b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
170b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h"
180b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
190b57cec5SDimitry Andric #include "clang/Sema/Lookup.h"
200fca6ea1SDimitry Andric #include "clang/Sema/Overload.h"
210b57cec5SDimitry Andric #include "clang/Sema/Scope.h"
220b57cec5SDimitry Andric #include "clang/Sema/ScopeInfo.h"
230b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h"
240fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h"
250fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenMP.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace clang;
280b57cec5SDimitry Andric using namespace sema;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric /// Determines if the given class is provably not derived from all of
330b57cec5SDimitry Andric /// the prospective base classes.
340b57cec5SDimitry Andric static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record,
350b57cec5SDimitry Andric                                      const BaseSet &Bases) {
360b57cec5SDimitry Andric   auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) {
370b57cec5SDimitry Andric     return !Bases.count(Base->getCanonicalDecl());
380b57cec5SDimitry Andric   };
390b57cec5SDimitry Andric   return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet);
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric enum IMAKind {
430b57cec5SDimitry Andric   /// The reference is definitely not an instance member access.
440b57cec5SDimitry Andric   IMA_Static,
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   /// The reference may be an implicit instance member access.
470b57cec5SDimitry Andric   IMA_Mixed,
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   /// The reference may be to an instance member, but it might be invalid if
500b57cec5SDimitry Andric   /// so, because the context is not an instance method.
515f757f3fSDimitry Andric   IMA_Mixed_StaticOrExplicitContext,
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   /// The reference may be to an instance member, but it is invalid if
540b57cec5SDimitry Andric   /// so, because the context is from an unrelated class.
550b57cec5SDimitry Andric   IMA_Mixed_Unrelated,
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   /// The reference is definitely an implicit instance member access.
580b57cec5SDimitry Andric   IMA_Instance,
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   /// The reference may be to an unresolved using declaration.
610b57cec5SDimitry Andric   IMA_Unresolved,
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   /// The reference is a contextually-permitted abstract member reference.
640b57cec5SDimitry Andric   IMA_Abstract,
650b57cec5SDimitry Andric 
660fca6ea1SDimitry Andric   /// Whether the context is static is dependent on the enclosing template (i.e.
670fca6ea1SDimitry Andric   /// in a dependent class scope explicit specialization).
680fca6ea1SDimitry Andric   IMA_Dependent,
690fca6ea1SDimitry Andric 
700b57cec5SDimitry Andric   /// The reference may be to an unresolved using declaration and the
710b57cec5SDimitry Andric   /// context is not an instance method.
725f757f3fSDimitry Andric   IMA_Unresolved_StaticOrExplicitContext,
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   // The reference refers to a field which is not a member of the containing
750b57cec5SDimitry Andric   // class, which is allowed because we're in C++11 mode and the context is
760b57cec5SDimitry Andric   // unevaluated.
770b57cec5SDimitry Andric   IMA_Field_Uneval_Context,
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   /// All possible referrents are instance members and the current
800b57cec5SDimitry Andric   /// context is not an instance method.
815f757f3fSDimitry Andric   IMA_Error_StaticOrExplicitContext,
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   /// All possible referrents are instance members of an unrelated
840b57cec5SDimitry Andric   /// class.
850b57cec5SDimitry Andric   IMA_Error_Unrelated
860b57cec5SDimitry Andric };
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric /// The given lookup names class member(s) and is not being used for
890b57cec5SDimitry Andric /// an address-of-member expression.  Classify the type of access
900b57cec5SDimitry Andric /// according to whether it's possible that this reference names an
910b57cec5SDimitry Andric /// instance member.  This is best-effort in dependent contexts; it is okay to
920b57cec5SDimitry Andric /// conservatively answer "yes", in which case some errors will simply
930b57cec5SDimitry Andric /// not be caught until template-instantiation.
940b57cec5SDimitry Andric static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
950b57cec5SDimitry Andric                                             const LookupResult &R) {
960b57cec5SDimitry Andric   assert(!R.empty() && (*R.begin())->isCXXClassMember());
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
990b57cec5SDimitry Andric 
1000fca6ea1SDimitry Andric   bool couldInstantiateToStatic = false;
1010fca6ea1SDimitry Andric   bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull();
1020b57cec5SDimitry Andric 
1030fca6ea1SDimitry Andric   if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) {
1040fca6ea1SDimitry Andric     if (MD->isImplicitObjectMemberFunction()) {
1050fca6ea1SDimitry Andric       isStaticOrExplicitContext = false;
1060fca6ea1SDimitry Andric       // A dependent class scope function template explicit specialization
1070fca6ea1SDimitry Andric       // that is neither declared 'static' nor with an explicit object
1080fca6ea1SDimitry Andric       // parameter could instantiate to a static or non-static member function.
1090fca6ea1SDimitry Andric       couldInstantiateToStatic = MD->getDependentSpecializationInfo();
1100fca6ea1SDimitry Andric     }
1110fca6ea1SDimitry Andric   }
1120fca6ea1SDimitry Andric 
1130fca6ea1SDimitry Andric   if (R.isUnresolvableResult()) {
1140fca6ea1SDimitry Andric     if (couldInstantiateToStatic)
1150fca6ea1SDimitry Andric       return IMA_Dependent;
1165f757f3fSDimitry Andric     return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext
1175f757f3fSDimitry Andric                                      : IMA_Unresolved;
1180fca6ea1SDimitry Andric   }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   // Collect all the declaring classes of instance members we find.
1210b57cec5SDimitry Andric   bool hasNonInstance = false;
1220b57cec5SDimitry Andric   bool isField = false;
1230b57cec5SDimitry Andric   BaseSet Classes;
1240b57cec5SDimitry Andric   for (NamedDecl *D : R) {
1250b57cec5SDimitry Andric     // Look through any using decls.
1260b57cec5SDimitry Andric     D = D->getUnderlyingDecl();
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric     if (D->isCXXInstanceMember()) {
1290b57cec5SDimitry Andric       isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) ||
1300b57cec5SDimitry Andric                  isa<IndirectFieldDecl>(D);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric       CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
1330b57cec5SDimitry Andric       Classes.insert(R->getCanonicalDecl());
1340b57cec5SDimitry Andric     } else
1350b57cec5SDimitry Andric       hasNonInstance = true;
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   // If we didn't find any instance members, it can't be an implicit
1390b57cec5SDimitry Andric   // member reference.
1400b57cec5SDimitry Andric   if (Classes.empty())
1410b57cec5SDimitry Andric     return IMA_Static;
1420b57cec5SDimitry Andric 
1430fca6ea1SDimitry Andric   if (couldInstantiateToStatic)
1440fca6ea1SDimitry Andric     return IMA_Dependent;
1450fca6ea1SDimitry Andric 
1460b57cec5SDimitry Andric   // C++11 [expr.prim.general]p12:
1470b57cec5SDimitry Andric   //   An id-expression that denotes a non-static data member or non-static
1480b57cec5SDimitry Andric   //   member function of a class can only be used:
1490b57cec5SDimitry Andric   //   (...)
1500b57cec5SDimitry Andric   //   - if that id-expression denotes a non-static data member and it
1510b57cec5SDimitry Andric   //     appears in an unevaluated operand.
1520b57cec5SDimitry Andric   //
1530b57cec5SDimitry Andric   // This rule is specific to C++11.  However, we also permit this form
1540b57cec5SDimitry Andric   // in unevaluated inline assembly operands, like the operand to a SIZE.
1550b57cec5SDimitry Andric   IMAKind AbstractInstanceResult = IMA_Static; // happens to be 'false'
1560b57cec5SDimitry Andric   assert(!AbstractInstanceResult);
1570b57cec5SDimitry Andric   switch (SemaRef.ExprEvalContexts.back().Context) {
1580b57cec5SDimitry Andric   case Sema::ExpressionEvaluationContext::Unevaluated:
1590b57cec5SDimitry Andric   case Sema::ExpressionEvaluationContext::UnevaluatedList:
1600b57cec5SDimitry Andric     if (isField && SemaRef.getLangOpts().CPlusPlus11)
1610b57cec5SDimitry Andric       AbstractInstanceResult = IMA_Field_Uneval_Context;
1620b57cec5SDimitry Andric     break;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
1650b57cec5SDimitry Andric     AbstractInstanceResult = IMA_Abstract;
1660b57cec5SDimitry Andric     break;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   case Sema::ExpressionEvaluationContext::DiscardedStatement:
1690b57cec5SDimitry Andric   case Sema::ExpressionEvaluationContext::ConstantEvaluated:
170349cc55cSDimitry Andric   case Sema::ExpressionEvaluationContext::ImmediateFunctionContext:
1710b57cec5SDimitry Andric   case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
1720b57cec5SDimitry Andric   case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
1730b57cec5SDimitry Andric     break;
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   // If the current context is not an instance method, it can't be
1770b57cec5SDimitry Andric   // an implicit member reference.
1785f757f3fSDimitry Andric   if (isStaticOrExplicitContext) {
1790b57cec5SDimitry Andric     if (hasNonInstance)
1805f757f3fSDimitry Andric       return IMA_Mixed_StaticOrExplicitContext;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     return AbstractInstanceResult ? AbstractInstanceResult
1835f757f3fSDimitry Andric                                   : IMA_Error_StaticOrExplicitContext;
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   CXXRecordDecl *contextClass;
18706c3fb27SDimitry Andric   if (auto *MD = dyn_cast<CXXMethodDecl>(DC))
1880b57cec5SDimitry Andric     contextClass = MD->getParent()->getCanonicalDecl();
18906c3fb27SDimitry Andric   else if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
19006c3fb27SDimitry Andric     contextClass = RD;
1910b57cec5SDimitry Andric   else
19206c3fb27SDimitry Andric     return AbstractInstanceResult ? AbstractInstanceResult
1935f757f3fSDimitry Andric                                   : IMA_Error_StaticOrExplicitContext;
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   // [class.mfct.non-static]p3:
1960b57cec5SDimitry Andric   // ...is used in the body of a non-static member function of class X,
1970b57cec5SDimitry Andric   // if name lookup (3.4.1) resolves the name in the id-expression to a
1980b57cec5SDimitry Andric   // non-static non-type member of some class C [...]
1990b57cec5SDimitry Andric   // ...if C is not X or a base class of X, the class member access expression
2000b57cec5SDimitry Andric   // is ill-formed.
2010b57cec5SDimitry Andric   if (R.getNamingClass() &&
2020b57cec5SDimitry Andric       contextClass->getCanonicalDecl() !=
2030b57cec5SDimitry Andric         R.getNamingClass()->getCanonicalDecl()) {
2040b57cec5SDimitry Andric     // If the naming class is not the current context, this was a qualified
2050b57cec5SDimitry Andric     // member name lookup, and it's sufficient to check that we have the naming
2060b57cec5SDimitry Andric     // class as a base class.
2070b57cec5SDimitry Andric     Classes.clear();
2080b57cec5SDimitry Andric     Classes.insert(R.getNamingClass()->getCanonicalDecl());
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   // If we can prove that the current context is unrelated to all the
2120b57cec5SDimitry Andric   // declaring classes, it can't be an implicit member reference (in
2130b57cec5SDimitry Andric   // which case it's an error if any of those members are selected).
2140b57cec5SDimitry Andric   if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes))
2150b57cec5SDimitry Andric     return hasNonInstance ? IMA_Mixed_Unrelated :
2160b57cec5SDimitry Andric            AbstractInstanceResult ? AbstractInstanceResult :
2170b57cec5SDimitry Andric                                     IMA_Error_Unrelated;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   return (hasNonInstance ? IMA_Mixed : IMA_Instance);
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric /// Diagnose a reference to a field with no object available.
2230b57cec5SDimitry Andric static void diagnoseInstanceReference(Sema &SemaRef,
2240b57cec5SDimitry Andric                                       const CXXScopeSpec &SS,
2250b57cec5SDimitry Andric                                       NamedDecl *Rep,
2260b57cec5SDimitry Andric                                       const DeclarationNameInfo &nameInfo) {
2270b57cec5SDimitry Andric   SourceLocation Loc = nameInfo.getLoc();
2280b57cec5SDimitry Andric   SourceRange Range(Loc);
2290b57cec5SDimitry Andric   if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   // Look through using shadow decls and aliases.
2320b57cec5SDimitry Andric   Rep = Rep->getUnderlyingDecl();
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
2350b57cec5SDimitry Andric   CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);
2360b57cec5SDimitry Andric   CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;
2370b57cec5SDimitry Andric   CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   bool InStaticMethod = Method && Method->isStatic();
2405f757f3fSDimitry Andric   bool InExplicitObjectMethod =
2415f757f3fSDimitry Andric       Method && Method->isExplicitObjectMemberFunction();
2420b57cec5SDimitry Andric   bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep);
2430b57cec5SDimitry Andric 
2445f757f3fSDimitry Andric   std::string Replacement;
2455f757f3fSDimitry Andric   if (InExplicitObjectMethod) {
2465f757f3fSDimitry Andric     DeclarationName N = Method->getParamDecl(0)->getDeclName();
2475f757f3fSDimitry Andric     if (!N.isEmpty()) {
2485f757f3fSDimitry Andric       Replacement.append(N.getAsString());
2495f757f3fSDimitry Andric       Replacement.append(".");
2505f757f3fSDimitry Andric     }
2515f757f3fSDimitry Andric   }
2520b57cec5SDimitry Andric   if (IsField && InStaticMethod)
2530b57cec5SDimitry Andric     // "invalid use of member 'x' in static member function"
2545f757f3fSDimitry Andric     SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)
2555f757f3fSDimitry Andric         << Range << nameInfo.getName() << /*static*/ 0;
2565f757f3fSDimitry Andric   else if (IsField && InExplicitObjectMethod) {
2575f757f3fSDimitry Andric     auto Diag = SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)
2585f757f3fSDimitry Andric                 << Range << nameInfo.getName() << /*explicit*/ 1;
2595f757f3fSDimitry Andric     if (!Replacement.empty())
2605f757f3fSDimitry Andric       Diag << FixItHint::CreateInsertion(Loc, Replacement);
2615f757f3fSDimitry Andric   } else if (ContextClass && RepClass && SS.isEmpty() &&
2625f757f3fSDimitry Andric              !InExplicitObjectMethod && !InStaticMethod &&
2635f757f3fSDimitry Andric              !RepClass->Equals(ContextClass) &&
2645f757f3fSDimitry Andric              RepClass->Encloses(ContextClass))
2650b57cec5SDimitry Andric     // Unqualified lookup in a non-static member function found a member of an
2660b57cec5SDimitry Andric     // enclosing class.
2670b57cec5SDimitry Andric     SemaRef.Diag(Loc, diag::err_nested_non_static_member_use)
2680b57cec5SDimitry Andric       << IsField << RepClass << nameInfo.getName() << ContextClass << Range;
2690b57cec5SDimitry Andric   else if (IsField)
2700b57cec5SDimitry Andric     SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
2710b57cec5SDimitry Andric       << nameInfo.getName() << Range;
2725f757f3fSDimitry Andric   else if (!InExplicitObjectMethod)
2730b57cec5SDimitry Andric     SemaRef.Diag(Loc, diag::err_member_call_without_object)
2745f757f3fSDimitry Andric         << Range << /*static*/ 0;
2755f757f3fSDimitry Andric   else {
276cb14a3feSDimitry Andric     if (const auto *Tpl = dyn_cast<FunctionTemplateDecl>(Rep))
277cb14a3feSDimitry Andric       Rep = Tpl->getTemplatedDecl();
278cb14a3feSDimitry Andric     const auto *Callee = cast<CXXMethodDecl>(Rep);
2795f757f3fSDimitry Andric     auto Diag = SemaRef.Diag(Loc, diag::err_member_call_without_object)
2805f757f3fSDimitry Andric                 << Range << Callee->isExplicitObjectMemberFunction();
2815f757f3fSDimitry Andric     if (!Replacement.empty())
2825f757f3fSDimitry Andric       Diag << FixItHint::CreateInsertion(Loc, Replacement);
2835f757f3fSDimitry Andric   }
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
2860fca6ea1SDimitry Andric bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS,
2870fca6ea1SDimitry Andric                                            LookupResult &R,
2880fca6ea1SDimitry Andric                                            bool IsAddressOfOperand) {
2890fca6ea1SDimitry Andric   if (!getLangOpts().CPlusPlus)
2900fca6ea1SDimitry Andric     return false;
2910fca6ea1SDimitry Andric   else if (R.empty() || !R.begin()->isCXXClassMember())
2920fca6ea1SDimitry Andric     return false;
2930fca6ea1SDimitry Andric   else if (!IsAddressOfOperand)
2940fca6ea1SDimitry Andric     return true;
2950fca6ea1SDimitry Andric   else if (!SS.isEmpty())
2960fca6ea1SDimitry Andric     return false;
2970fca6ea1SDimitry Andric   else if (R.isOverloadedResult())
2980fca6ea1SDimitry Andric     return false;
2990fca6ea1SDimitry Andric   else if (R.isUnresolvableResult())
3000fca6ea1SDimitry Andric     return true;
3010fca6ea1SDimitry Andric   else
3020fca6ea1SDimitry Andric     return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl());
3030fca6ea1SDimitry Andric }
3040fca6ea1SDimitry Andric 
305e8d8bef9SDimitry Andric ExprResult Sema::BuildPossibleImplicitMemberExpr(
306e8d8bef9SDimitry Andric     const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
3070fca6ea1SDimitry Andric     const TemplateArgumentListInfo *TemplateArgs, const Scope *S) {
3080fca6ea1SDimitry Andric   switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {
3090b57cec5SDimitry Andric   case IMA_Instance:
3100b57cec5SDimitry Andric   case IMA_Mixed:
3110b57cec5SDimitry Andric   case IMA_Mixed_Unrelated:
3120b57cec5SDimitry Andric   case IMA_Unresolved:
3130fca6ea1SDimitry Andric     return BuildImplicitMemberExpr(
3140fca6ea1SDimitry Andric         SS, TemplateKWLoc, R, TemplateArgs,
3150fca6ea1SDimitry Andric         /*IsKnownInstance=*/Classification == IMA_Instance, S);
3160b57cec5SDimitry Andric   case IMA_Field_Uneval_Context:
3170b57cec5SDimitry Andric     Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
3180b57cec5SDimitry Andric       << R.getLookupNameInfo().getName();
319bdd1243dSDimitry Andric     [[fallthrough]];
3200b57cec5SDimitry Andric   case IMA_Static:
3210b57cec5SDimitry Andric   case IMA_Abstract:
3225f757f3fSDimitry Andric   case IMA_Mixed_StaticOrExplicitContext:
3235f757f3fSDimitry Andric   case IMA_Unresolved_StaticOrExplicitContext:
3240b57cec5SDimitry Andric     if (TemplateArgs || TemplateKWLoc.isValid())
3250fca6ea1SDimitry Andric       return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,
3260fca6ea1SDimitry Andric                                  TemplateArgs);
3270fca6ea1SDimitry Andric     return BuildDeclarationNameExpr(SS, R, /*NeedsADL=*/false,
3280fca6ea1SDimitry Andric                                     /*AcceptInvalidDecl=*/false);
3290fca6ea1SDimitry Andric   case IMA_Dependent:
3300fca6ea1SDimitry Andric     R.suppressDiagnostics();
3310fca6ea1SDimitry Andric     return UnresolvedLookupExpr::Create(
3320fca6ea1SDimitry Andric         Context, R.getNamingClass(), SS.getWithLocInContext(Context),
3330fca6ea1SDimitry Andric         TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false,
334*62987288SDimitry Andric         TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true,
335*62987288SDimitry Andric         /*KnownInstantiationDependent=*/true);
3360b57cec5SDimitry Andric 
3375f757f3fSDimitry Andric   case IMA_Error_StaticOrExplicitContext:
3380b57cec5SDimitry Andric   case IMA_Error_Unrelated:
3390b57cec5SDimitry Andric     diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
3400b57cec5SDimitry Andric                               R.getLookupNameInfo());
3410b57cec5SDimitry Andric     return ExprError();
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   llvm_unreachable("unexpected instance member access kind");
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric /// Determine whether input char is from rgba component set.
3480b57cec5SDimitry Andric static bool
3490b57cec5SDimitry Andric IsRGBA(char c) {
3500b57cec5SDimitry Andric   switch (c) {
3510b57cec5SDimitry Andric   case 'r':
3520b57cec5SDimitry Andric   case 'g':
3530b57cec5SDimitry Andric   case 'b':
3540b57cec5SDimitry Andric   case 'a':
3550b57cec5SDimitry Andric     return true;
3560b57cec5SDimitry Andric   default:
3570b57cec5SDimitry Andric     return false;
3580b57cec5SDimitry Andric   }
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric // OpenCL v1.1, s6.1.7
3620b57cec5SDimitry Andric // The component swizzle length must be in accordance with the acceptable
3630b57cec5SDimitry Andric // vector sizes.
3640b57cec5SDimitry Andric static bool IsValidOpenCLComponentSwizzleLength(unsigned len)
3650b57cec5SDimitry Andric {
3660b57cec5SDimitry Andric   return (len >= 1 && len <= 4) || len == 8 || len == 16;
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric /// Check an ext-vector component access expression.
3700b57cec5SDimitry Andric ///
3710b57cec5SDimitry Andric /// VK should be set in advance to the value kind of the base
3720b57cec5SDimitry Andric /// expression.
3730b57cec5SDimitry Andric static QualType
3740b57cec5SDimitry Andric CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
3750b57cec5SDimitry Andric                         SourceLocation OpLoc, const IdentifierInfo *CompName,
3760b57cec5SDimitry Andric                         SourceLocation CompLoc) {
3770b57cec5SDimitry Andric   // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,
3780b57cec5SDimitry Andric   // see FIXME there.
3790b57cec5SDimitry Andric   //
3800b57cec5SDimitry Andric   // FIXME: This logic can be greatly simplified by splitting it along
3810b57cec5SDimitry Andric   // halving/not halving and reworking the component checking.
3820b57cec5SDimitry Andric   const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   // The vector accessor can't exceed the number of elements.
3850b57cec5SDimitry Andric   const char *compStr = CompName->getNameStart();
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   // This flag determines whether or not the component is one of the four
3880b57cec5SDimitry Andric   // special names that indicate a subset of exactly half the elements are
3890b57cec5SDimitry Andric   // to be selected.
3900b57cec5SDimitry Andric   bool HalvingSwizzle = false;
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   // This flag determines whether or not CompName has an 's' char prefix,
3930b57cec5SDimitry Andric   // indicating that it is a string of hex values to be used as vector indices.
3940b57cec5SDimitry Andric   bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1];
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric   bool HasRepeated = false;
3970b57cec5SDimitry Andric   bool HasIndex[16] = {};
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   int Idx;
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   // Check that we've found one of the special components, or that the component
4020b57cec5SDimitry Andric   // names must come from the same set.
4030b57cec5SDimitry Andric   if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
4040b57cec5SDimitry Andric       !strcmp(compStr, "even") || !strcmp(compStr, "odd")) {
4050b57cec5SDimitry Andric     HalvingSwizzle = true;
4060b57cec5SDimitry Andric   } else if (!HexSwizzle &&
4070b57cec5SDimitry Andric              (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
4080b57cec5SDimitry Andric     bool HasRGBA = IsRGBA(*compStr);
4090b57cec5SDimitry Andric     do {
4100b57cec5SDimitry Andric       // Ensure that xyzw and rgba components don't intermingle.
4110b57cec5SDimitry Andric       if (HasRGBA != IsRGBA(*compStr))
4120b57cec5SDimitry Andric         break;
4130b57cec5SDimitry Andric       if (HasIndex[Idx]) HasRepeated = true;
4140b57cec5SDimitry Andric       HasIndex[Idx] = true;
4150b57cec5SDimitry Andric       compStr++;
4160b57cec5SDimitry Andric     } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);
4170b57cec5SDimitry Andric 
418fe6060f1SDimitry Andric     // Emit a warning if an rgba selector is used earlier than OpenCL C 3.0.
4190b57cec5SDimitry Andric     if (HasRGBA || (*compStr && IsRGBA(*compStr))) {
420349cc55cSDimitry Andric       if (S.getLangOpts().OpenCL &&
421349cc55cSDimitry Andric           S.getLangOpts().getOpenCLCompatibleVersion() < 300) {
4220b57cec5SDimitry Andric         const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr;
4230b57cec5SDimitry Andric         S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector)
424fe6060f1SDimitry Andric             << StringRef(DiagBegin, 1) << SourceRange(CompLoc);
4250b57cec5SDimitry Andric       }
4260b57cec5SDimitry Andric     }
4270b57cec5SDimitry Andric   } else {
4280b57cec5SDimitry Andric     if (HexSwizzle) compStr++;
4290b57cec5SDimitry Andric     while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
4300b57cec5SDimitry Andric       if (HasIndex[Idx]) HasRepeated = true;
4310b57cec5SDimitry Andric       HasIndex[Idx] = true;
4320b57cec5SDimitry Andric       compStr++;
4330b57cec5SDimitry Andric     }
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   if (!HalvingSwizzle && *compStr) {
4370b57cec5SDimitry Andric     // We didn't get to the end of the string. This means the component names
4380b57cec5SDimitry Andric     // didn't come from the same set *or* we encountered an illegal name.
4390b57cec5SDimitry Andric     S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
4400b57cec5SDimitry Andric       << StringRef(compStr, 1) << SourceRange(CompLoc);
4410b57cec5SDimitry Andric     return QualType();
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   // Ensure no component accessor exceeds the width of the vector type it
4450b57cec5SDimitry Andric   // operates on.
4460b57cec5SDimitry Andric   if (!HalvingSwizzle) {
4470b57cec5SDimitry Andric     compStr = CompName->getNameStart();
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric     if (HexSwizzle)
4500b57cec5SDimitry Andric       compStr++;
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric     while (*compStr) {
4530b57cec5SDimitry Andric       if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) {
4540b57cec5SDimitry Andric         S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
4550b57cec5SDimitry Andric           << baseType << SourceRange(CompLoc);
4560b57cec5SDimitry Andric         return QualType();
4570b57cec5SDimitry Andric       }
4580b57cec5SDimitry Andric     }
4590b57cec5SDimitry Andric   }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   // OpenCL mode requires swizzle length to be in accordance with accepted
4620b57cec5SDimitry Andric   // sizes. Clang however supports arbitrary lengths for other languages.
4630b57cec5SDimitry Andric   if (S.getLangOpts().OpenCL && !HalvingSwizzle) {
4640b57cec5SDimitry Andric     unsigned SwizzleLength = CompName->getLength();
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric     if (HexSwizzle)
4670b57cec5SDimitry Andric       SwizzleLength--;
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric     if (IsValidOpenCLComponentSwizzleLength(SwizzleLength) == false) {
4700b57cec5SDimitry Andric       S.Diag(OpLoc, diag::err_opencl_ext_vector_component_invalid_length)
4710b57cec5SDimitry Andric         << SwizzleLength << SourceRange(CompLoc);
4720b57cec5SDimitry Andric       return QualType();
4730b57cec5SDimitry Andric     }
4740b57cec5SDimitry Andric   }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   // The component accessor looks fine - now we need to compute the actual type.
4770b57cec5SDimitry Andric   // The vector type is implied by the component accessor. For example,
4780b57cec5SDimitry Andric   // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.
4790b57cec5SDimitry Andric   // vec4.s0 is a float, vec4.s23 is a vec3, etc.
4800b57cec5SDimitry Andric   // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.
4810b57cec5SDimitry Andric   unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2
4820b57cec5SDimitry Andric                                      : CompName->getLength();
4830b57cec5SDimitry Andric   if (HexSwizzle)
4840b57cec5SDimitry Andric     CompSize--;
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   if (CompSize == 1)
4870b57cec5SDimitry Andric     return vecType->getElementType();
4880b57cec5SDimitry Andric 
489fe6060f1SDimitry Andric   if (HasRepeated)
490fe6060f1SDimitry Andric     VK = VK_PRValue;
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);
4930b57cec5SDimitry Andric   // Now look up the TypeDefDecl from the vector type. Without this,
4940b57cec5SDimitry Andric   // diagostics look bad. We want extended vector types to appear built-in.
4950b57cec5SDimitry Andric   for (Sema::ExtVectorDeclsType::iterator
4960b57cec5SDimitry Andric          I = S.ExtVectorDecls.begin(S.getExternalSource()),
4970b57cec5SDimitry Andric          E = S.ExtVectorDecls.end();
4980b57cec5SDimitry Andric        I != E; ++I) {
4990b57cec5SDimitry Andric     if ((*I)->getUnderlyingType() == VT)
5000b57cec5SDimitry Andric       return S.Context.getTypedefType(*I);
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   return VT; // should never get here (a typedef type should always be found).
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
5070b57cec5SDimitry Andric                                                 IdentifierInfo *Member,
5080b57cec5SDimitry Andric                                                 const Selector &Sel,
5090b57cec5SDimitry Andric                                                 ASTContext &Context) {
5100b57cec5SDimitry Andric   if (Member)
5110b57cec5SDimitry Andric     if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(
5120b57cec5SDimitry Andric             Member, ObjCPropertyQueryKind::OBJC_PR_query_instance))
5130b57cec5SDimitry Andric       return PD;
5140b57cec5SDimitry Andric   if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
5150b57cec5SDimitry Andric     return OMD;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   for (const auto *I : PDecl->protocols()) {
5180b57cec5SDimitry Andric     if (Decl *D = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel,
5190b57cec5SDimitry Andric                                                            Context))
5200b57cec5SDimitry Andric       return D;
5210b57cec5SDimitry Andric   }
5220b57cec5SDimitry Andric   return nullptr;
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
5260b57cec5SDimitry Andric                                       IdentifierInfo *Member,
5270b57cec5SDimitry Andric                                       const Selector &Sel,
5280b57cec5SDimitry Andric                                       ASTContext &Context) {
5290b57cec5SDimitry Andric   // Check protocols on qualified interfaces.
5300b57cec5SDimitry Andric   Decl *GDecl = nullptr;
5310b57cec5SDimitry Andric   for (const auto *I : QIdTy->quals()) {
5320b57cec5SDimitry Andric     if (Member)
5330b57cec5SDimitry Andric       if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(
5340b57cec5SDimitry Andric               Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
5350b57cec5SDimitry Andric         GDecl = PD;
5360b57cec5SDimitry Andric         break;
5370b57cec5SDimitry Andric       }
5380b57cec5SDimitry Andric     // Also must look for a getter or setter name which uses property syntax.
5390b57cec5SDimitry Andric     if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) {
5400b57cec5SDimitry Andric       GDecl = OMD;
5410b57cec5SDimitry Andric       break;
5420b57cec5SDimitry Andric     }
5430b57cec5SDimitry Andric   }
5440b57cec5SDimitry Andric   if (!GDecl) {
5450b57cec5SDimitry Andric     for (const auto *I : QIdTy->quals()) {
5460b57cec5SDimitry Andric       // Search in the protocol-qualifier list of current protocol.
5470b57cec5SDimitry Andric       GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context);
5480b57cec5SDimitry Andric       if (GDecl)
5490b57cec5SDimitry Andric         return GDecl;
5500b57cec5SDimitry Andric     }
5510b57cec5SDimitry Andric   }
5520b57cec5SDimitry Andric   return GDecl;
5530b57cec5SDimitry Andric }
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric ExprResult
5560b57cec5SDimitry Andric Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
5570b57cec5SDimitry Andric                                bool IsArrow, SourceLocation OpLoc,
5580b57cec5SDimitry Andric                                const CXXScopeSpec &SS,
5590b57cec5SDimitry Andric                                SourceLocation TemplateKWLoc,
5600b57cec5SDimitry Andric                                NamedDecl *FirstQualifierInScope,
5610b57cec5SDimitry Andric                                const DeclarationNameInfo &NameInfo,
5620b57cec5SDimitry Andric                                const TemplateArgumentListInfo *TemplateArgs) {
5630b57cec5SDimitry Andric   // Even in dependent contexts, try to diagnose base expressions with
5640b57cec5SDimitry Andric   // obviously wrong types, e.g.:
5650b57cec5SDimitry Andric   //
5660b57cec5SDimitry Andric   // T* t;
5670b57cec5SDimitry Andric   // t.f;
5680b57cec5SDimitry Andric   //
5690b57cec5SDimitry Andric   // In Obj-C++, however, the above expression is valid, since it could be
5700b57cec5SDimitry Andric   // accessing the 'f' property if T is an Obj-C interface. The extra check
5710b57cec5SDimitry Andric   // allows this, while still reporting an error if T is a struct pointer.
5720b57cec5SDimitry Andric   if (!IsArrow) {
5730b57cec5SDimitry Andric     const PointerType *PT = BaseType->getAs<PointerType>();
5740b57cec5SDimitry Andric     if (PT && (!getLangOpts().ObjC ||
5750b57cec5SDimitry Andric                PT->getPointeeType()->isRecordType())) {
5760b57cec5SDimitry Andric       assert(BaseExpr && "cannot happen with implicit member accesses");
5770b57cec5SDimitry Andric       Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
5780b57cec5SDimitry Andric         << BaseType << BaseExpr->getSourceRange() << NameInfo.getSourceRange();
5790b57cec5SDimitry Andric       return ExprError();
5800b57cec5SDimitry Andric     }
5810b57cec5SDimitry Andric   }
5820b57cec5SDimitry Andric 
58304eeddc0SDimitry Andric   assert(BaseType->isDependentType() || NameInfo.getName().isDependentName() ||
58404eeddc0SDimitry Andric          isDependentScopeSpecifier(SS) ||
58504eeddc0SDimitry Andric          (TemplateArgs && llvm::any_of(TemplateArgs->arguments(),
58604eeddc0SDimitry Andric                                        [](const TemplateArgumentLoc &Arg) {
58704eeddc0SDimitry Andric                                          return Arg.getArgument().isDependent();
58804eeddc0SDimitry Andric                                        })));
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
5910b57cec5SDimitry Andric   // must have pointer type, and the accessed type is the pointee.
5920b57cec5SDimitry Andric   return CXXDependentScopeMemberExpr::Create(
5930b57cec5SDimitry Andric       Context, BaseExpr, BaseType, IsArrow, OpLoc,
5940b57cec5SDimitry Andric       SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope,
5950b57cec5SDimitry Andric       NameInfo, TemplateArgs);
5960b57cec5SDimitry Andric }
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric /// We know that the given qualified member reference points only to
5990b57cec5SDimitry Andric /// declarations which do not belong to the static type of the base
6000b57cec5SDimitry Andric /// expression.  Diagnose the problem.
6010b57cec5SDimitry Andric static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
6020b57cec5SDimitry Andric                                              Expr *BaseExpr,
6030b57cec5SDimitry Andric                                              QualType BaseType,
6040b57cec5SDimitry Andric                                              const CXXScopeSpec &SS,
6050b57cec5SDimitry Andric                                              NamedDecl *rep,
6060b57cec5SDimitry Andric                                        const DeclarationNameInfo &nameInfo) {
6070b57cec5SDimitry Andric   // If this is an implicit member access, use a different set of
6080b57cec5SDimitry Andric   // diagnostics.
6090b57cec5SDimitry Andric   if (!BaseExpr)
6100b57cec5SDimitry Andric     return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo);
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)
6130b57cec5SDimitry Andric     << SS.getRange() << rep << BaseType;
6140b57cec5SDimitry Andric }
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
6170b57cec5SDimitry Andric                                          QualType BaseType,
6180b57cec5SDimitry Andric                                          const CXXScopeSpec &SS,
6190b57cec5SDimitry Andric                                          const LookupResult &R) {
6200b57cec5SDimitry Andric   CXXRecordDecl *BaseRecord =
6210b57cec5SDimitry Andric     cast_or_null<CXXRecordDecl>(computeDeclContext(BaseType));
6220b57cec5SDimitry Andric   if (!BaseRecord) {
6230b57cec5SDimitry Andric     // We can't check this yet because the base type is still
6240b57cec5SDimitry Andric     // dependent.
6250b57cec5SDimitry Andric     assert(BaseType->isDependentType());
6260b57cec5SDimitry Andric     return false;
6270b57cec5SDimitry Andric   }
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric   for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
6300b57cec5SDimitry Andric     // If this is an implicit member reference and we find a
6310b57cec5SDimitry Andric     // non-instance member, it's not an error.
6320b57cec5SDimitry Andric     if (!BaseExpr && !(*I)->isCXXInstanceMember())
6330b57cec5SDimitry Andric       return false;
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric     // Note that we use the DC of the decl, not the underlying decl.
636349cc55cSDimitry Andric     DeclContext *DC = (*I)->getDeclContext()->getNonTransparentContext();
6370b57cec5SDimitry Andric     if (!DC->isRecord())
6380b57cec5SDimitry Andric       continue;
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric     CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl();
6410b57cec5SDimitry Andric     if (BaseRecord->getCanonicalDecl() == MemberRecord ||
6420b57cec5SDimitry Andric         !BaseRecord->isProvablyNotDerivedFrom(MemberRecord))
6430b57cec5SDimitry Andric       return false;
6440b57cec5SDimitry Andric   }
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS,
6470b57cec5SDimitry Andric                                    R.getRepresentativeDecl(),
6480b57cec5SDimitry Andric                                    R.getLookupNameInfo());
6490b57cec5SDimitry Andric   return true;
6500b57cec5SDimitry Andric }
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric namespace {
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric // Callback to only accept typo corrections that are either a ValueDecl or a
6550b57cec5SDimitry Andric // FunctionTemplateDecl and are declared in the current record or, for a C++
6560b57cec5SDimitry Andric // classes, one of its base classes.
6570b57cec5SDimitry Andric class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
6580b57cec5SDimitry Andric public:
6590fca6ea1SDimitry Andric   explicit RecordMemberExprValidatorCCC(QualType RTy)
6600fca6ea1SDimitry Andric       : Record(RTy->getAsRecordDecl()) {
6610b57cec5SDimitry Andric     // Don't add bare keywords to the consumer since they will always fail
6620b57cec5SDimitry Andric     // validation by virtue of not being associated with any decls.
6630b57cec5SDimitry Andric     WantTypeSpecifiers = false;
6640b57cec5SDimitry Andric     WantExpressionKeywords = false;
6650b57cec5SDimitry Andric     WantCXXNamedCasts = false;
6660b57cec5SDimitry Andric     WantFunctionLikeCasts = false;
6670b57cec5SDimitry Andric     WantRemainingKeywords = false;
6680b57cec5SDimitry Andric   }
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   bool ValidateCandidate(const TypoCorrection &candidate) override {
6710b57cec5SDimitry Andric     NamedDecl *ND = candidate.getCorrectionDecl();
6720b57cec5SDimitry Andric     // Don't accept candidates that cannot be member functions, constants,
6730b57cec5SDimitry Andric     // variables, or templates.
6740b57cec5SDimitry Andric     if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)))
6750b57cec5SDimitry Andric       return false;
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric     // Accept candidates that occur in the current record.
6780b57cec5SDimitry Andric     if (Record->containsDecl(ND))
6790b57cec5SDimitry Andric       return true;
6800b57cec5SDimitry Andric 
681349cc55cSDimitry Andric     if (const auto *RD = dyn_cast<CXXRecordDecl>(Record)) {
6820b57cec5SDimitry Andric       // Accept candidates that occur in any of the current class' base classes.
6830b57cec5SDimitry Andric       for (const auto &BS : RD->bases()) {
684349cc55cSDimitry Andric         if (const auto *BSTy = BS.getType()->getAs<RecordType>()) {
6850b57cec5SDimitry Andric           if (BSTy->getDecl()->containsDecl(ND))
6860b57cec5SDimitry Andric             return true;
6870b57cec5SDimitry Andric         }
6880b57cec5SDimitry Andric       }
6890b57cec5SDimitry Andric     }
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric     return false;
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric   std::unique_ptr<CorrectionCandidateCallback> clone() override {
695a7dea167SDimitry Andric     return std::make_unique<RecordMemberExprValidatorCCC>(*this);
6960b57cec5SDimitry Andric   }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric private:
6990b57cec5SDimitry Andric   const RecordDecl *const Record;
7000b57cec5SDimitry Andric };
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric }
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
7050fca6ea1SDimitry Andric                                      Expr *BaseExpr, QualType RTy,
7060b57cec5SDimitry Andric                                      SourceLocation OpLoc, bool IsArrow,
7070b57cec5SDimitry Andric                                      CXXScopeSpec &SS, bool HasTemplateArgs,
7080b57cec5SDimitry Andric                                      SourceLocation TemplateKWLoc,
7090b57cec5SDimitry Andric                                      TypoExpr *&TE) {
7100b57cec5SDimitry Andric   SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
7110fca6ea1SDimitry Andric   if (!RTy->isDependentType() &&
7120fca6ea1SDimitry Andric       !SemaRef.isThisOutsideMemberFunctionBody(RTy) &&
7130fca6ea1SDimitry Andric       SemaRef.RequireCompleteType(
7140fca6ea1SDimitry Andric           OpLoc, RTy, diag::err_typecheck_incomplete_tag, BaseRange))
7150b57cec5SDimitry Andric     return true;
7160b57cec5SDimitry Andric 
7170fca6ea1SDimitry Andric   // LookupTemplateName/LookupParsedName don't expect these both to exist
7180fca6ea1SDimitry Andric   // simultaneously.
7190fca6ea1SDimitry Andric   QualType ObjectType = SS.isSet() ? QualType() : RTy;
7200fca6ea1SDimitry Andric   if (HasTemplateArgs || TemplateKWLoc.isValid())
7210fca6ea1SDimitry Andric     return SemaRef.LookupTemplateName(R,
7220fca6ea1SDimitry Andric                                       /*S=*/nullptr, SS, ObjectType,
7230fca6ea1SDimitry Andric                                       /*EnteringContext=*/false, TemplateKWLoc);
7240b57cec5SDimitry Andric 
7250fca6ea1SDimitry Andric   SemaRef.LookupParsedName(R, /*S=*/nullptr, &SS, ObjectType);
7260b57cec5SDimitry Andric 
7270fca6ea1SDimitry Andric   if (!R.empty() || R.wasNotFoundInCurrentInstantiation())
7280b57cec5SDimitry Andric     return false;
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric   DeclarationName Typo = R.getLookupName();
7310b57cec5SDimitry Andric   SourceLocation TypoLoc = R.getNameLoc();
7320fca6ea1SDimitry Andric   // Recompute the lookup context.
7330fca6ea1SDimitry Andric   DeclContext *DC = SS.isSet() ? SemaRef.computeDeclContext(SS)
7340fca6ea1SDimitry Andric                                : SemaRef.computeDeclContext(RTy);
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric   struct QueryState {
7370b57cec5SDimitry Andric     Sema &SemaRef;
7380b57cec5SDimitry Andric     DeclarationNameInfo NameInfo;
7390b57cec5SDimitry Andric     Sema::LookupNameKind LookupKind;
7400fca6ea1SDimitry Andric     RedeclarationKind Redecl;
7410b57cec5SDimitry Andric   };
7420b57cec5SDimitry Andric   QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
7430b57cec5SDimitry Andric                   R.redeclarationKind()};
7440b57cec5SDimitry Andric   RecordMemberExprValidatorCCC CCC(RTy);
7450b57cec5SDimitry Andric   TE = SemaRef.CorrectTypoDelayed(
7460b57cec5SDimitry Andric       R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC,
7470b57cec5SDimitry Andric       [=, &SemaRef](const TypoCorrection &TC) {
7480b57cec5SDimitry Andric         if (TC) {
7490b57cec5SDimitry Andric           assert(!TC.isKeyword() &&
7500b57cec5SDimitry Andric                  "Got a keyword as a correction for a member!");
7510b57cec5SDimitry Andric           bool DroppedSpecifier =
7520b57cec5SDimitry Andric               TC.WillReplaceSpecifier() &&
7530b57cec5SDimitry Andric               Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts());
7540b57cec5SDimitry Andric           SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
7550b57cec5SDimitry Andric                                        << Typo << DC << DroppedSpecifier
7560b57cec5SDimitry Andric                                        << SS.getRange());
7570b57cec5SDimitry Andric         } else {
7580fca6ea1SDimitry Andric           SemaRef.Diag(TypoLoc, diag::err_no_member)
7590fca6ea1SDimitry Andric               << Typo << DC << (SS.isSet() ? SS.getRange() : BaseRange);
7600b57cec5SDimitry Andric         }
7610b57cec5SDimitry Andric       },
7620b57cec5SDimitry Andric       [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {
7630b57cec5SDimitry Andric         LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl);
7640b57cec5SDimitry Andric         R.clear(); // Ensure there's no decls lingering in the shared state.
7650b57cec5SDimitry Andric         R.suppressDiagnostics();
7660b57cec5SDimitry Andric         R.setLookupName(TC.getCorrection());
7670b57cec5SDimitry Andric         for (NamedDecl *ND : TC)
7680b57cec5SDimitry Andric           R.addDecl(ND);
7690b57cec5SDimitry Andric         R.resolveKind();
7700b57cec5SDimitry Andric         return SemaRef.BuildMemberReferenceExpr(
7710b57cec5SDimitry Andric             BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),
7720b57cec5SDimitry Andric             nullptr, R, nullptr, nullptr);
7730b57cec5SDimitry Andric       },
7740b57cec5SDimitry Andric       Sema::CTK_ErrorRecovery, DC);
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric   return false;
7770b57cec5SDimitry Andric }
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
7800b57cec5SDimitry Andric                                    ExprResult &BaseExpr, bool &IsArrow,
7810b57cec5SDimitry Andric                                    SourceLocation OpLoc, CXXScopeSpec &SS,
7820b57cec5SDimitry Andric                                    Decl *ObjCImpDecl, bool HasTemplateArgs,
7830b57cec5SDimitry Andric                                    SourceLocation TemplateKWLoc);
7840b57cec5SDimitry Andric 
7850fca6ea1SDimitry Andric ExprResult Sema::BuildMemberReferenceExpr(
7860fca6ea1SDimitry Andric     Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
7870fca6ea1SDimitry Andric     CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
7880fca6ea1SDimitry Andric     NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
7890fca6ea1SDimitry Andric     const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
7900b57cec5SDimitry Andric     ActOnMemberAccessExtraArgs *ExtraArgs) {
7910b57cec5SDimitry Andric   LookupResult R(*this, NameInfo, LookupMemberName);
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric   // Implicit member accesses.
7940b57cec5SDimitry Andric   if (!Base) {
7950b57cec5SDimitry Andric     TypoExpr *TE = nullptr;
7960b57cec5SDimitry Andric     QualType RecordTy = BaseType;
797fe6060f1SDimitry Andric     if (IsArrow) RecordTy = RecordTy->castAs<PointerType>()->getPointeeType();
7980fca6ea1SDimitry Andric     if (LookupMemberExprInRecord(*this, R, nullptr, RecordTy, OpLoc, IsArrow,
7990fca6ea1SDimitry Andric                                  SS, TemplateArgs != nullptr, TemplateKWLoc,
8000fca6ea1SDimitry Andric                                  TE))
8010b57cec5SDimitry Andric       return ExprError();
8020b57cec5SDimitry Andric     if (TE)
8030b57cec5SDimitry Andric       return TE;
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric   // Explicit member accesses.
8060b57cec5SDimitry Andric   } else {
8070b57cec5SDimitry Andric     ExprResult BaseResult = Base;
8080b57cec5SDimitry Andric     ExprResult Result =
8090b57cec5SDimitry Andric         LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS,
8100b57cec5SDimitry Andric                          ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
8110b57cec5SDimitry Andric                          TemplateArgs != nullptr, TemplateKWLoc);
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric     if (BaseResult.isInvalid())
8140b57cec5SDimitry Andric       return ExprError();
8150b57cec5SDimitry Andric     Base = BaseResult.get();
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric     if (Result.isInvalid())
8180b57cec5SDimitry Andric       return ExprError();
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric     if (Result.get())
8210b57cec5SDimitry Andric       return Result;
8220b57cec5SDimitry Andric 
8230b57cec5SDimitry Andric     // LookupMemberExpr can modify Base, and thus change BaseType
8240b57cec5SDimitry Andric     BaseType = Base->getType();
8250b57cec5SDimitry Andric   }
8260b57cec5SDimitry Andric 
8270fca6ea1SDimitry Andric   // BuildMemberReferenceExpr expects the nested-name-specifier, if any, to be
8280fca6ea1SDimitry Andric   // valid.
8290fca6ea1SDimitry Andric   if (SS.isInvalid())
8300fca6ea1SDimitry Andric     return ExprError();
8310fca6ea1SDimitry Andric 
8320b57cec5SDimitry Andric   return BuildMemberReferenceExpr(Base, BaseType,
8330b57cec5SDimitry Andric                                   OpLoc, IsArrow, SS, TemplateKWLoc,
8340b57cec5SDimitry Andric                                   FirstQualifierInScope, R, TemplateArgs, S,
8350b57cec5SDimitry Andric                                   false, ExtraArgs);
8360b57cec5SDimitry Andric }
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric ExprResult
8390b57cec5SDimitry Andric Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
8400b57cec5SDimitry Andric                                                SourceLocation loc,
8410b57cec5SDimitry Andric                                                IndirectFieldDecl *indirectField,
8420b57cec5SDimitry Andric                                                DeclAccessPair foundDecl,
8430b57cec5SDimitry Andric                                                Expr *baseObjectExpr,
8440b57cec5SDimitry Andric                                                SourceLocation opLoc) {
8450b57cec5SDimitry Andric   // First, build the expression that refers to the base object.
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   // Case 1:  the base of the indirect field is not a field.
8480b57cec5SDimitry Andric   VarDecl *baseVariable = indirectField->getVarDecl();
8490b57cec5SDimitry Andric   CXXScopeSpec EmptySS;
8500b57cec5SDimitry Andric   if (baseVariable) {
8510b57cec5SDimitry Andric     assert(baseVariable->getType()->isRecordType());
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric     // In principle we could have a member access expression that
8540b57cec5SDimitry Andric     // accesses an anonymous struct/union that's a static member of
8550b57cec5SDimitry Andric     // the base object's class.  However, under the current standard,
8560b57cec5SDimitry Andric     // static data members cannot be anonymous structs or unions.
8570b57cec5SDimitry Andric     // Supporting this is as easy as building a MemberExpr here.
8580b57cec5SDimitry Andric     assert(!baseObjectExpr && "anonymous struct/union is static data member?");
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric     DeclarationNameInfo baseNameInfo(DeclarationName(), loc);
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric     ExprResult result
8630b57cec5SDimitry Andric       = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
8640b57cec5SDimitry Andric     if (result.isInvalid()) return ExprError();
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric     baseObjectExpr = result.get();
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   assert((baseVariable || baseObjectExpr) &&
8700b57cec5SDimitry Andric          "referencing anonymous struct/union without a base variable or "
8710b57cec5SDimitry Andric          "expression");
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   // Build the implicit member references to the field of the
8740b57cec5SDimitry Andric   // anonymous struct/union.
8750b57cec5SDimitry Andric   Expr *result = baseObjectExpr;
8760b57cec5SDimitry Andric   IndirectFieldDecl::chain_iterator
8770b57cec5SDimitry Andric   FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric   // Case 2: the base of the indirect field is a field and the user
8800b57cec5SDimitry Andric   // wrote a member expression.
8810b57cec5SDimitry Andric   if (!baseVariable) {
8820b57cec5SDimitry Andric     FieldDecl *field = cast<FieldDecl>(*FI);
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric     bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType();
8850b57cec5SDimitry Andric 
8860b57cec5SDimitry Andric     // Make a nameInfo that properly uses the anonymous name.
8870b57cec5SDimitry Andric     DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric     // Build the first member access in the chain with full information.
8900b57cec5SDimitry Andric     result =
8910b57cec5SDimitry Andric         BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(),
8920b57cec5SDimitry Andric                                 SS, field, foundDecl, memberNameInfo)
8930b57cec5SDimitry Andric             .get();
8940b57cec5SDimitry Andric     if (!result)
8950b57cec5SDimitry Andric       return ExprError();
8960b57cec5SDimitry Andric   }
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric   // In all cases, we should now skip the first declaration in the chain.
8990b57cec5SDimitry Andric   ++FI;
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   while (FI != FEnd) {
9020b57cec5SDimitry Andric     FieldDecl *field = cast<FieldDecl>(*FI++);
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric     // FIXME: these are somewhat meaningless
9050b57cec5SDimitry Andric     DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
9060b57cec5SDimitry Andric     DeclAccessPair fakeFoundDecl =
9070b57cec5SDimitry Andric         DeclAccessPair::make(field, field->getAccess());
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric     result =
9100b57cec5SDimitry Andric         BuildFieldReferenceExpr(result, /*isarrow*/ false, SourceLocation(),
9110b57cec5SDimitry Andric                                 (FI == FEnd ? SS : EmptySS), field,
9120b57cec5SDimitry Andric                                 fakeFoundDecl, memberNameInfo)
9130b57cec5SDimitry Andric             .get();
9140b57cec5SDimitry Andric   }
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric   return result;
9170b57cec5SDimitry Andric }
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric static ExprResult
9200b57cec5SDimitry Andric BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
9210b57cec5SDimitry Andric                        const CXXScopeSpec &SS,
9220b57cec5SDimitry Andric                        MSPropertyDecl *PD,
9230b57cec5SDimitry Andric                        const DeclarationNameInfo &NameInfo) {
9240b57cec5SDimitry Andric   // Property names are always simple identifiers and therefore never
9250b57cec5SDimitry Andric   // require any interesting additional storage.
9260b57cec5SDimitry Andric   return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,
9270b57cec5SDimitry Andric                                            S.Context.PseudoObjectTy, VK_LValue,
9280b57cec5SDimitry Andric                                            SS.getWithLocInContext(S.Context),
9290b57cec5SDimitry Andric                                            NameInfo.getLoc());
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric MemberExpr *Sema::BuildMemberExpr(
9330b57cec5SDimitry Andric     Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS,
9340b57cec5SDimitry Andric     SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
9350b57cec5SDimitry Andric     bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
9360b57cec5SDimitry Andric     QualType Ty, ExprValueKind VK, ExprObjectKind OK,
9370b57cec5SDimitry Andric     const TemplateArgumentListInfo *TemplateArgs) {
938fe6060f1SDimitry Andric   assert((!IsArrow || Base->isPRValue()) &&
939fe6060f1SDimitry Andric          "-> base must be a pointer prvalue");
9400b57cec5SDimitry Andric   MemberExpr *E =
9410b57cec5SDimitry Andric       MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc,
9420b57cec5SDimitry Andric                          Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty,
9430b57cec5SDimitry Andric                          VK, OK, getNonOdrUseReasonInCurrentContext(Member));
9440b57cec5SDimitry Andric   E->setHadMultipleCandidates(HadMultipleCandidates);
9450b57cec5SDimitry Andric   MarkMemberReferenced(E);
946480093f4SDimitry Andric 
947480093f4SDimitry Andric   // C++ [except.spec]p17:
948480093f4SDimitry Andric   //   An exception-specification is considered to be needed when:
949480093f4SDimitry Andric   //   - in an expression the function is the unique lookup result or the
950480093f4SDimitry Andric   //     selected member of a set of overloaded functions
951480093f4SDimitry Andric   if (auto *FPT = Ty->getAs<FunctionProtoType>()) {
952480093f4SDimitry Andric     if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
953480093f4SDimitry Andric       if (auto *NewFPT = ResolveExceptionSpec(MemberNameInfo.getLoc(), FPT))
954480093f4SDimitry Andric         E->setType(Context.getQualifiedType(NewFPT, Ty.getQualifiers()));
955480093f4SDimitry Andric     }
956480093f4SDimitry Andric   }
957480093f4SDimitry Andric 
9580b57cec5SDimitry Andric   return E;
9590b57cec5SDimitry Andric }
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric /// Determine if the given scope is within a function-try-block handler.
9620b57cec5SDimitry Andric static bool IsInFnTryBlockHandler(const Scope *S) {
9630b57cec5SDimitry Andric   // Walk the scope stack until finding a FnTryCatchScope, or leave the
9640b57cec5SDimitry Andric   // function scope. If a FnTryCatchScope is found, check whether the TryScope
9650b57cec5SDimitry Andric   // flag is set. If it is not, it's a function-try-block handler.
9660b57cec5SDimitry Andric   for (; S != S->getFnParent(); S = S->getParent()) {
96781ad6265SDimitry Andric     if (S->isFnTryCatchScope())
9680b57cec5SDimitry Andric       return (S->getFlags() & Scope::TryScope) != Scope::TryScope;
9690b57cec5SDimitry Andric   }
9700b57cec5SDimitry Andric   return false;
9710b57cec5SDimitry Andric }
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric ExprResult
9740b57cec5SDimitry Andric Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
9750b57cec5SDimitry Andric                                SourceLocation OpLoc, bool IsArrow,
9760b57cec5SDimitry Andric                                const CXXScopeSpec &SS,
9770b57cec5SDimitry Andric                                SourceLocation TemplateKWLoc,
9780b57cec5SDimitry Andric                                NamedDecl *FirstQualifierInScope,
9790b57cec5SDimitry Andric                                LookupResult &R,
9800b57cec5SDimitry Andric                                const TemplateArgumentListInfo *TemplateArgs,
9810b57cec5SDimitry Andric                                const Scope *S,
9820b57cec5SDimitry Andric                                bool SuppressQualifierCheck,
9830b57cec5SDimitry Andric                                ActOnMemberAccessExtraArgs *ExtraArgs) {
9840fca6ea1SDimitry Andric   assert(!SS.isInvalid() && "nested-name-specifier cannot be invalid");
9850fca6ea1SDimitry Andric   // If the member wasn't found in the current instantiation, or if the
9860fca6ea1SDimitry Andric   // arrow operator was used with a dependent non-pointer object expression,
9870fca6ea1SDimitry Andric   // build a CXXDependentScopeMemberExpr.
9880fca6ea1SDimitry Andric   if (R.wasNotFoundInCurrentInstantiation() ||
9890fca6ea1SDimitry Andric       (R.getLookupName().getCXXOverloadedOperator() == OO_Equal &&
9900fca6ea1SDimitry Andric        (SS.isSet() ? SS.getScopeRep()->isDependent()
9910fca6ea1SDimitry Andric                    : BaseExprType->isDependentType())))
9920fca6ea1SDimitry Andric     return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS,
9930fca6ea1SDimitry Andric                                     TemplateKWLoc, FirstQualifierInScope,
9940fca6ea1SDimitry Andric                                     R.getLookupNameInfo(), TemplateArgs);
9950fca6ea1SDimitry Andric 
9960b57cec5SDimitry Andric   QualType BaseType = BaseExprType;
9970b57cec5SDimitry Andric   if (IsArrow) {
9980b57cec5SDimitry Andric     assert(BaseType->isPointerType());
9990b57cec5SDimitry Andric     BaseType = BaseType->castAs<PointerType>()->getPointeeType();
10000b57cec5SDimitry Andric   }
10010b57cec5SDimitry Andric   R.setBaseObjectType(BaseType);
10020b57cec5SDimitry Andric 
10030fca6ea1SDimitry Andric   assert((SS.isEmpty()
10040fca6ea1SDimitry Andric               ? !BaseType->isDependentType() || computeDeclContext(BaseType)
10050fca6ea1SDimitry Andric               : !isDependentScopeSpecifier(SS) || computeDeclContext(SS)) &&
10060fca6ea1SDimitry Andric          "dependent lookup context that isn't the current instantiation?");
10070fca6ea1SDimitry Andric 
10080b57cec5SDimitry Andric   // C++1z [expr.ref]p2:
10090b57cec5SDimitry Andric   //   For the first option (dot) the first expression shall be a glvalue [...]
1010fe6060f1SDimitry Andric   if (!IsArrow && BaseExpr && BaseExpr->isPRValue()) {
10110b57cec5SDimitry Andric     ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);
10120b57cec5SDimitry Andric     if (Converted.isInvalid())
10130b57cec5SDimitry Andric       return ExprError();
10140b57cec5SDimitry Andric     BaseExpr = Converted.get();
10150b57cec5SDimitry Andric   }
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
10180b57cec5SDimitry Andric   DeclarationName MemberName = MemberNameInfo.getName();
10190b57cec5SDimitry Andric   SourceLocation MemberLoc = MemberNameInfo.getLoc();
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric   if (R.isAmbiguous())
10220b57cec5SDimitry Andric     return ExprError();
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric   // [except.handle]p10: Referring to any non-static member or base class of an
10250b57cec5SDimitry Andric   // object in the handler for a function-try-block of a constructor or
10260b57cec5SDimitry Andric   // destructor for that object results in undefined behavior.
10270b57cec5SDimitry Andric   const auto *FD = getCurFunctionDecl();
10280b57cec5SDimitry Andric   if (S && BaseExpr && FD &&
10290b57cec5SDimitry Andric       (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
10300b57cec5SDimitry Andric       isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) &&
10310b57cec5SDimitry Andric       IsInFnTryBlockHandler(S))
10320b57cec5SDimitry Andric     Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr)
10330b57cec5SDimitry Andric         << isa<CXXDestructorDecl>(FD);
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   if (R.empty()) {
10360fca6ea1SDimitry Andric     ExprResult RetryExpr = ExprError();
10370fca6ea1SDimitry Andric     if (ExtraArgs && !IsArrow && BaseExpr && !BaseExpr->isTypeDependent()) {
10380b57cec5SDimitry Andric       SFINAETrap Trap(*this, true);
10390b57cec5SDimitry Andric       ParsedType ObjectType;
10400b57cec5SDimitry Andric       bool MayBePseudoDestructor = false;
10410fca6ea1SDimitry Andric       RetryExpr = ActOnStartCXXMemberReference(getCurScope(), BaseExpr, OpLoc,
10420fca6ea1SDimitry Andric                                                tok::arrow, ObjectType,
10430b57cec5SDimitry Andric                                                MayBePseudoDestructor);
10440b57cec5SDimitry Andric       if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {
10450b57cec5SDimitry Andric         CXXScopeSpec TempSS(SS);
10460b57cec5SDimitry Andric         RetryExpr = ActOnMemberAccessExpr(
10470b57cec5SDimitry Andric             ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,
10480b57cec5SDimitry Andric             TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);
10490b57cec5SDimitry Andric       }
10500b57cec5SDimitry Andric       if (Trap.hasErrorOccurred())
10510b57cec5SDimitry Andric         RetryExpr = ExprError();
10520b57cec5SDimitry Andric     }
10530fca6ea1SDimitry Andric 
10540fca6ea1SDimitry Andric     // Rederive where we looked up.
10550fca6ea1SDimitry Andric     DeclContext *DC =
10560fca6ea1SDimitry Andric         (SS.isSet() ? computeDeclContext(SS) : computeDeclContext(BaseType));
10570fca6ea1SDimitry Andric     assert(DC);
10580fca6ea1SDimitry Andric 
10590fca6ea1SDimitry Andric     if (RetryExpr.isUsable())
10600b57cec5SDimitry Andric       Diag(OpLoc, diag::err_no_member_overloaded_arrow)
10610b57cec5SDimitry Andric           << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->");
10620fca6ea1SDimitry Andric     else
10630b57cec5SDimitry Andric       Diag(R.getNameLoc(), diag::err_no_member)
10640b57cec5SDimitry Andric           << MemberName << DC
10650fca6ea1SDimitry Andric           << (SS.isSet()
10660fca6ea1SDimitry Andric                   ? SS.getRange()
10670fca6ea1SDimitry Andric                   : (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()));
10680fca6ea1SDimitry Andric     return RetryExpr;
10690b57cec5SDimitry Andric   }
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   // Diagnose lookups that find only declarations from a non-base
10720b57cec5SDimitry Andric   // type.  This is possible for either qualified lookups (which may
10730b57cec5SDimitry Andric   // have been qualified with an unrelated type) or implicit member
10740b57cec5SDimitry Andric   // expressions (which were found with unqualified lookup and thus
10750b57cec5SDimitry Andric   // may have come from an enclosing scope).  Note that it's okay for
10760b57cec5SDimitry Andric   // lookup to find declarations from a non-base type as long as those
10770b57cec5SDimitry Andric   // aren't the ones picked by overload resolution.
10780b57cec5SDimitry Andric   if ((SS.isSet() || !BaseExpr ||
10790b57cec5SDimitry Andric        (isa<CXXThisExpr>(BaseExpr) &&
10800b57cec5SDimitry Andric         cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&
10810b57cec5SDimitry Andric       !SuppressQualifierCheck &&
10820b57cec5SDimitry Andric       CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
10830b57cec5SDimitry Andric     return ExprError();
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric   // Construct an unresolved result if we in fact got an unresolved
10860b57cec5SDimitry Andric   // result.
10870b57cec5SDimitry Andric   if (R.isOverloadedResult() || R.isUnresolvableResult()) {
10880b57cec5SDimitry Andric     // Suppress any lookup-related diagnostics; we'll do these when we
10890b57cec5SDimitry Andric     // pick a member.
10900b57cec5SDimitry Andric     R.suppressDiagnostics();
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric     UnresolvedMemberExpr *MemExpr
10930b57cec5SDimitry Andric       = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(),
10940b57cec5SDimitry Andric                                      BaseExpr, BaseExprType,
10950b57cec5SDimitry Andric                                      IsArrow, OpLoc,
10960b57cec5SDimitry Andric                                      SS.getWithLocInContext(Context),
10970b57cec5SDimitry Andric                                      TemplateKWLoc, MemberNameInfo,
10980b57cec5SDimitry Andric                                      TemplateArgs, R.begin(), R.end());
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric     return MemExpr;
11010b57cec5SDimitry Andric   }
11020b57cec5SDimitry Andric 
11030b57cec5SDimitry Andric   assert(R.isSingleResult());
11040b57cec5SDimitry Andric   DeclAccessPair FoundDecl = R.begin().getPair();
11050b57cec5SDimitry Andric   NamedDecl *MemberDecl = R.getFoundDecl();
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   // FIXME: diagnose the presence of template arguments now.
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric   // If the decl being referenced had an error, return an error for this
11100b57cec5SDimitry Andric   // sub-expr without emitting another error, in order to avoid cascading
11110b57cec5SDimitry Andric   // error cases.
11120b57cec5SDimitry Andric   if (MemberDecl->isInvalidDecl())
11130b57cec5SDimitry Andric     return ExprError();
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric   // Handle the implicit-member-access case.
11160b57cec5SDimitry Andric   if (!BaseExpr) {
11170b57cec5SDimitry Andric     // If this is not an instance member, convert to a non-member access.
11180b57cec5SDimitry Andric     if (!MemberDecl->isCXXInstanceMember()) {
1119e8d8bef9SDimitry Andric       // We might have a variable template specialization (or maybe one day a
1120e8d8bef9SDimitry Andric       // member concept-id).
1121e8d8bef9SDimitry Andric       if (TemplateArgs || TemplateKWLoc.isValid())
1122e8d8bef9SDimitry Andric         return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/false, TemplateArgs);
1123e8d8bef9SDimitry Andric 
11240b57cec5SDimitry Andric       return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl,
11250b57cec5SDimitry Andric                                       FoundDecl, TemplateArgs);
11260b57cec5SDimitry Andric     }
11270b57cec5SDimitry Andric     SourceLocation Loc = R.getNameLoc();
11280b57cec5SDimitry Andric     if (SS.getRange().isValid())
11290b57cec5SDimitry Andric       Loc = SS.getRange().getBegin();
11300b57cec5SDimitry Andric     BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true);
11310b57cec5SDimitry Andric   }
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric   // Check the use of this member.
11340b57cec5SDimitry Andric   if (DiagnoseUseOfDecl(MemberDecl, MemberLoc))
11350b57cec5SDimitry Andric     return ExprError();
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric   if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
11380b57cec5SDimitry Andric     return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl,
11390b57cec5SDimitry Andric                                    MemberNameInfo);
11400b57cec5SDimitry Andric 
11410b57cec5SDimitry Andric   if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))
11420b57cec5SDimitry Andric     return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,
11430b57cec5SDimitry Andric                                   MemberNameInfo);
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric   if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
11460b57cec5SDimitry Andric     // We may have found a field within an anonymous union or struct
11470b57cec5SDimitry Andric     // (C++ [class.union]).
11480b57cec5SDimitry Andric     return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
11490b57cec5SDimitry Andric                                                     FoundDecl, BaseExpr,
11500b57cec5SDimitry Andric                                                     OpLoc);
11510b57cec5SDimitry Andric 
11520b57cec5SDimitry Andric   if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
11530fca6ea1SDimitry Andric     return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,
11540fca6ea1SDimitry Andric                            SS.getWithLocInContext(Context), TemplateKWLoc, Var,
11550b57cec5SDimitry Andric                            FoundDecl, /*HadMultipleCandidates=*/false,
11560b57cec5SDimitry Andric                            MemberNameInfo, Var->getType().getNonReferenceType(),
11570b57cec5SDimitry Andric                            VK_LValue, OK_Ordinary);
11580b57cec5SDimitry Andric   }
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric   if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
11610b57cec5SDimitry Andric     ExprValueKind valueKind;
11620b57cec5SDimitry Andric     QualType type;
11630b57cec5SDimitry Andric     if (MemberFn->isInstance()) {
1164fe6060f1SDimitry Andric       valueKind = VK_PRValue;
11650b57cec5SDimitry Andric       type = Context.BoundMemberTy;
11660b57cec5SDimitry Andric     } else {
11670b57cec5SDimitry Andric       valueKind = VK_LValue;
11680b57cec5SDimitry Andric       type = MemberFn->getType();
11690b57cec5SDimitry Andric     }
11700b57cec5SDimitry Andric 
11710fca6ea1SDimitry Andric     return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,
11720fca6ea1SDimitry Andric                            SS.getWithLocInContext(Context), TemplateKWLoc,
11730b57cec5SDimitry Andric                            MemberFn, FoundDecl, /*HadMultipleCandidates=*/false,
11740b57cec5SDimitry Andric                            MemberNameInfo, type, valueKind, OK_Ordinary);
11750b57cec5SDimitry Andric   }
11760b57cec5SDimitry Andric   assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
11770b57cec5SDimitry Andric 
11780b57cec5SDimitry Andric   if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
11790fca6ea1SDimitry Andric     return BuildMemberExpr(
11800fca6ea1SDimitry Andric         BaseExpr, IsArrow, OpLoc, SS.getWithLocInContext(Context),
11810fca6ea1SDimitry Andric         TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandidates=*/false,
11820fca6ea1SDimitry Andric         MemberNameInfo, Enum->getType(), VK_PRValue, OK_Ordinary);
11830b57cec5SDimitry Andric   }
1184e8d8bef9SDimitry Andric 
11850b57cec5SDimitry Andric   if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
1186e8d8bef9SDimitry Andric     if (!TemplateArgs) {
11870fca6ea1SDimitry Andric       diagnoseMissingTemplateArguments(
11880fca6ea1SDimitry Andric           SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc);
1189e8d8bef9SDimitry Andric       return ExprError();
1190e8d8bef9SDimitry Andric     }
1191e8d8bef9SDimitry Andric 
1192e8d8bef9SDimitry Andric     DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc,
1193e8d8bef9SDimitry Andric                                           MemberNameInfo.getLoc(), *TemplateArgs);
1194e8d8bef9SDimitry Andric     if (VDecl.isInvalid())
1195e8d8bef9SDimitry Andric       return ExprError();
1196e8d8bef9SDimitry Andric 
1197e8d8bef9SDimitry Andric     // Non-dependent member, but dependent template arguments.
1198e8d8bef9SDimitry Andric     if (!VDecl.get())
1199e8d8bef9SDimitry Andric       return ActOnDependentMemberExpr(
1200e8d8bef9SDimitry Andric           BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc,
1201e8d8bef9SDimitry Andric           FirstQualifierInScope, MemberNameInfo, TemplateArgs);
1202e8d8bef9SDimitry Andric 
1203e8d8bef9SDimitry Andric     VarDecl *Var = cast<VarDecl>(VDecl.get());
1204e8d8bef9SDimitry Andric     if (!Var->getTemplateSpecializationKind())
1205e8d8bef9SDimitry Andric       Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc);
1206e8d8bef9SDimitry Andric 
12070fca6ea1SDimitry Andric     return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,
12080fca6ea1SDimitry Andric                            SS.getWithLocInContext(Context), TemplateKWLoc, Var,
1209bdd1243dSDimitry Andric                            FoundDecl, /*HadMultipleCandidates=*/false,
1210bdd1243dSDimitry Andric                            MemberNameInfo, Var->getType().getNonReferenceType(),
1211bdd1243dSDimitry Andric                            VK_LValue, OK_Ordinary, TemplateArgs);
12120b57cec5SDimitry Andric   }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric   // We found something that we didn't expect. Complain.
12150b57cec5SDimitry Andric   if (isa<TypeDecl>(MemberDecl))
12160b57cec5SDimitry Andric     Diag(MemberLoc, diag::err_typecheck_member_reference_type)
12170b57cec5SDimitry Andric       << MemberName << BaseType << int(IsArrow);
12180b57cec5SDimitry Andric   else
12190b57cec5SDimitry Andric     Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)
12200b57cec5SDimitry Andric       << MemberName << BaseType << int(IsArrow);
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric   Diag(MemberDecl->getLocation(), diag::note_member_declared_here)
12230b57cec5SDimitry Andric     << MemberName;
12240b57cec5SDimitry Andric   R.suppressDiagnostics();
12250b57cec5SDimitry Andric   return ExprError();
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric /// Given that normal member access failed on the given expression,
12290b57cec5SDimitry Andric /// and given that the expression's type involves builtin-id or
12300b57cec5SDimitry Andric /// builtin-Class, decide whether substituting in the redefinition
12310b57cec5SDimitry Andric /// types would be profitable.  The redefinition type is whatever
12320b57cec5SDimitry Andric /// this translation unit tried to typedef to id/Class;  we store
12330b57cec5SDimitry Andric /// it to the side and then re-use it in places like this.
12340b57cec5SDimitry Andric static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) {
12350b57cec5SDimitry Andric   const ObjCObjectPointerType *opty
12360b57cec5SDimitry Andric     = base.get()->getType()->getAs<ObjCObjectPointerType>();
12370b57cec5SDimitry Andric   if (!opty) return false;
12380b57cec5SDimitry Andric 
12390b57cec5SDimitry Andric   const ObjCObjectType *ty = opty->getObjectType();
12400b57cec5SDimitry Andric 
12410b57cec5SDimitry Andric   QualType redef;
12420b57cec5SDimitry Andric   if (ty->isObjCId()) {
12430b57cec5SDimitry Andric     redef = S.Context.getObjCIdRedefinitionType();
12440b57cec5SDimitry Andric   } else if (ty->isObjCClass()) {
12450b57cec5SDimitry Andric     redef = S.Context.getObjCClassRedefinitionType();
12460b57cec5SDimitry Andric   } else {
12470b57cec5SDimitry Andric     return false;
12480b57cec5SDimitry Andric   }
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric   // Do the substitution as long as the redefinition type isn't just a
12510b57cec5SDimitry Andric   // possibly-qualified pointer to builtin-id or builtin-Class again.
12520b57cec5SDimitry Andric   opty = redef->getAs<ObjCObjectPointerType>();
12530b57cec5SDimitry Andric   if (opty && !opty->getObjectType()->getInterface())
12540b57cec5SDimitry Andric     return false;
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric   base = S.ImpCastExprToType(base.get(), redef, CK_BitCast);
12570b57cec5SDimitry Andric   return true;
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric static bool isRecordType(QualType T) {
12610b57cec5SDimitry Andric   return T->isRecordType();
12620b57cec5SDimitry Andric }
12630b57cec5SDimitry Andric static bool isPointerToRecordType(QualType T) {
12640b57cec5SDimitry Andric   if (const PointerType *PT = T->getAs<PointerType>())
12650b57cec5SDimitry Andric     return PT->getPointeeType()->isRecordType();
12660b57cec5SDimitry Andric   return false;
12670b57cec5SDimitry Andric }
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric ExprResult
12700b57cec5SDimitry Andric Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {
12710b57cec5SDimitry Andric   if (IsArrow && !Base->getType()->isFunctionType())
12720b57cec5SDimitry Andric     return DefaultFunctionArrayLvalueConversion(Base);
12730b57cec5SDimitry Andric 
12740b57cec5SDimitry Andric   return CheckPlaceholderExpr(Base);
12750b57cec5SDimitry Andric }
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric /// Look up the given member of the given non-type-dependent
12780b57cec5SDimitry Andric /// expression.  This can return in one of two ways:
12790b57cec5SDimitry Andric ///  * If it returns a sentinel null-but-valid result, the caller will
12800b57cec5SDimitry Andric ///    assume that lookup was performed and the results written into
12810b57cec5SDimitry Andric ///    the provided structure.  It will take over from there.
12820b57cec5SDimitry Andric ///  * Otherwise, the returned expression will be produced in place of
12830b57cec5SDimitry Andric ///    an ordinary member expression.
12840b57cec5SDimitry Andric ///
12850b57cec5SDimitry Andric /// The ObjCImpDecl bit is a gross hack that will need to be properly
12860b57cec5SDimitry Andric /// fixed for ObjC++.
12870b57cec5SDimitry Andric static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
12880b57cec5SDimitry Andric                                    ExprResult &BaseExpr, bool &IsArrow,
12890b57cec5SDimitry Andric                                    SourceLocation OpLoc, CXXScopeSpec &SS,
12900b57cec5SDimitry Andric                                    Decl *ObjCImpDecl, bool HasTemplateArgs,
12910b57cec5SDimitry Andric                                    SourceLocation TemplateKWLoc) {
12920b57cec5SDimitry Andric   assert(BaseExpr.get() && "no base expression");
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric   // Perform default conversions.
12950b57cec5SDimitry Andric   BaseExpr = S.PerformMemberExprBaseConversion(BaseExpr.get(), IsArrow);
12960b57cec5SDimitry Andric   if (BaseExpr.isInvalid())
12970b57cec5SDimitry Andric     return ExprError();
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric   QualType BaseType = BaseExpr.get()->getType();
13000b57cec5SDimitry Andric 
13010b57cec5SDimitry Andric   DeclarationName MemberName = R.getLookupName();
13020b57cec5SDimitry Andric   SourceLocation MemberLoc = R.getNameLoc();
13030b57cec5SDimitry Andric 
13040b57cec5SDimitry Andric   // For later type-checking purposes, turn arrow accesses into dot
13050b57cec5SDimitry Andric   // accesses.  The only access type we support that doesn't follow
13060b57cec5SDimitry Andric   // the C equivalence "a->b === (*a).b" is ObjC property accesses,
13070b57cec5SDimitry Andric   // and those never use arrows, so this is unaffected.
13080b57cec5SDimitry Andric   if (IsArrow) {
13090b57cec5SDimitry Andric     if (const PointerType *Ptr = BaseType->getAs<PointerType>())
13100b57cec5SDimitry Andric       BaseType = Ptr->getPointeeType();
13110fca6ea1SDimitry Andric     else if (const ObjCObjectPointerType *Ptr =
13120fca6ea1SDimitry Andric                  BaseType->getAs<ObjCObjectPointerType>())
13130b57cec5SDimitry Andric       BaseType = Ptr->getPointeeType();
13140fca6ea1SDimitry Andric     else if (BaseType->isFunctionType())
13150fca6ea1SDimitry Andric       goto fail;
13160fca6ea1SDimitry Andric     else if (BaseType->isDependentType())
13170fca6ea1SDimitry Andric       BaseType = S.Context.DependentTy;
13180b57cec5SDimitry Andric     else if (BaseType->isRecordType()) {
13190b57cec5SDimitry Andric       // Recover from arrow accesses to records, e.g.:
13200b57cec5SDimitry Andric       //   struct MyRecord foo;
13210b57cec5SDimitry Andric       //   foo->bar
13220b57cec5SDimitry Andric       // This is actually well-formed in C++ if MyRecord has an
13230b57cec5SDimitry Andric       // overloaded operator->, but that should have been dealt with
13240b57cec5SDimitry Andric       // by now--or a diagnostic message already issued if a problem
13250b57cec5SDimitry Andric       // was encountered while looking for the overloaded operator->.
13260b57cec5SDimitry Andric       if (!S.getLangOpts().CPlusPlus) {
13270b57cec5SDimitry Andric         S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
13280b57cec5SDimitry Andric             << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
13290b57cec5SDimitry Andric             << FixItHint::CreateReplacement(OpLoc, ".");
13300b57cec5SDimitry Andric       }
13310b57cec5SDimitry Andric       IsArrow = false;
13320b57cec5SDimitry Andric     } else {
13330b57cec5SDimitry Andric       S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
13340b57cec5SDimitry Andric           << BaseType << BaseExpr.get()->getSourceRange();
13350b57cec5SDimitry Andric       return ExprError();
13360b57cec5SDimitry Andric     }
13370b57cec5SDimitry Andric   }
13380b57cec5SDimitry Andric 
133981ad6265SDimitry Andric   // If the base type is an atomic type, this access is undefined behavior per
134081ad6265SDimitry Andric   // C11 6.5.2.3p5. Instead of giving a typecheck error, we'll warn the user
134181ad6265SDimitry Andric   // about the UB and recover by converting the atomic lvalue into a non-atomic
134281ad6265SDimitry Andric   // lvalue. Because this is inherently unsafe as an atomic operation, the
134381ad6265SDimitry Andric   // warning defaults to an error.
134481ad6265SDimitry Andric   if (const auto *ATy = BaseType->getAs<AtomicType>()) {
134581ad6265SDimitry Andric     S.DiagRuntimeBehavior(OpLoc, nullptr,
134681ad6265SDimitry Andric                           S.PDiag(diag::warn_atomic_member_access));
134781ad6265SDimitry Andric     BaseType = ATy->getValueType().getUnqualifiedType();
134881ad6265SDimitry Andric     BaseExpr = ImplicitCastExpr::Create(
134981ad6265SDimitry Andric         S.Context, IsArrow ? S.Context.getPointerType(BaseType) : BaseType,
135081ad6265SDimitry Andric         CK_AtomicToNonAtomic, BaseExpr.get(), nullptr,
135181ad6265SDimitry Andric         BaseExpr.get()->getValueKind(), FPOptionsOverride());
135281ad6265SDimitry Andric   }
135381ad6265SDimitry Andric 
13540b57cec5SDimitry Andric   // Handle field access to simple records.
13550fca6ea1SDimitry Andric   if (BaseType->getAsRecordDecl()) {
13560b57cec5SDimitry Andric     TypoExpr *TE = nullptr;
13570fca6ea1SDimitry Andric     if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow,
13580fca6ea1SDimitry Andric                                  SS, HasTemplateArgs, TemplateKWLoc, TE))
13590b57cec5SDimitry Andric       return ExprError();
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric     // Returning valid-but-null is how we indicate to the caller that
13620b57cec5SDimitry Andric     // the lookup result was filled in. If typo correction was attempted and
13630b57cec5SDimitry Andric     // failed, the lookup result will have been cleared--that combined with the
13640b57cec5SDimitry Andric     // valid-but-null ExprResult will trigger the appropriate diagnostics.
13650b57cec5SDimitry Andric     return ExprResult(TE);
13660fca6ea1SDimitry Andric   } else if (BaseType->isDependentType()) {
13670fca6ea1SDimitry Andric     R.setNotFoundInCurrentInstantiation();
13680fca6ea1SDimitry Andric     return ExprEmpty();
13690b57cec5SDimitry Andric   }
13700b57cec5SDimitry Andric 
13710b57cec5SDimitry Andric   // Handle ivar access to Objective-C objects.
13720b57cec5SDimitry Andric   if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) {
13730b57cec5SDimitry Andric     if (!SS.isEmpty() && !SS.isInvalid()) {
13740b57cec5SDimitry Andric       S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
13750b57cec5SDimitry Andric         << 1 << SS.getScopeRep()
13760b57cec5SDimitry Andric         << FixItHint::CreateRemoval(SS.getRange());
13770b57cec5SDimitry Andric       SS.clear();
13780b57cec5SDimitry Andric     }
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric     IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric     // There are three cases for the base type:
13830b57cec5SDimitry Andric     //   - builtin id (qualified or unqualified)
13840b57cec5SDimitry Andric     //   - builtin Class (qualified or unqualified)
13850b57cec5SDimitry Andric     //   - an interface
13860b57cec5SDimitry Andric     ObjCInterfaceDecl *IDecl = OTy->getInterface();
13870b57cec5SDimitry Andric     if (!IDecl) {
13880b57cec5SDimitry Andric       if (S.getLangOpts().ObjCAutoRefCount &&
13890b57cec5SDimitry Andric           (OTy->isObjCId() || OTy->isObjCClass()))
13900b57cec5SDimitry Andric         goto fail;
13910b57cec5SDimitry Andric       // There's an implicit 'isa' ivar on all objects.
13920b57cec5SDimitry Andric       // But we only actually find it this way on objects of type 'id',
13930b57cec5SDimitry Andric       // apparently.
13940b57cec5SDimitry Andric       if (OTy->isObjCId() && Member->isStr("isa"))
13950b57cec5SDimitry Andric         return new (S.Context) ObjCIsaExpr(BaseExpr.get(), IsArrow, MemberLoc,
13960b57cec5SDimitry Andric                                            OpLoc, S.Context.getObjCClassType());
13970b57cec5SDimitry Andric       if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
13980b57cec5SDimitry Andric         return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
13990b57cec5SDimitry Andric                                 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
14000b57cec5SDimitry Andric       goto fail;
14010b57cec5SDimitry Andric     }
14020b57cec5SDimitry Andric 
14030b57cec5SDimitry Andric     if (S.RequireCompleteType(OpLoc, BaseType,
14040b57cec5SDimitry Andric                               diag::err_typecheck_incomplete_tag,
14050b57cec5SDimitry Andric                               BaseExpr.get()))
14060b57cec5SDimitry Andric       return ExprError();
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric     ObjCInterfaceDecl *ClassDeclared = nullptr;
14090b57cec5SDimitry Andric     ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
14100b57cec5SDimitry Andric 
14110b57cec5SDimitry Andric     if (!IV) {
14120b57cec5SDimitry Andric       // Attempt to correct for typos in ivar names.
14130b57cec5SDimitry Andric       DeclFilterCCC<ObjCIvarDecl> Validator{};
14140b57cec5SDimitry Andric       Validator.IsObjCIvarLookup = IsArrow;
14150b57cec5SDimitry Andric       if (TypoCorrection Corrected = S.CorrectTypo(
14160b57cec5SDimitry Andric               R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
14170b57cec5SDimitry Andric               Validator, Sema::CTK_ErrorRecovery, IDecl)) {
14180b57cec5SDimitry Andric         IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
14190b57cec5SDimitry Andric         S.diagnoseTypo(
14200b57cec5SDimitry Andric             Corrected,
14210b57cec5SDimitry Andric             S.PDiag(diag::err_typecheck_member_reference_ivar_suggest)
14220b57cec5SDimitry Andric                 << IDecl->getDeclName() << MemberName);
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric         // Figure out the class that declares the ivar.
14250b57cec5SDimitry Andric         assert(!ClassDeclared);
14260b57cec5SDimitry Andric 
14270b57cec5SDimitry Andric         Decl *D = cast<Decl>(IV->getDeclContext());
14280b57cec5SDimitry Andric         if (auto *Category = dyn_cast<ObjCCategoryDecl>(D))
14290b57cec5SDimitry Andric           D = Category->getClassInterface();
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric         if (auto *Implementation = dyn_cast<ObjCImplementationDecl>(D))
14320b57cec5SDimitry Andric           ClassDeclared = Implementation->getClassInterface();
14330b57cec5SDimitry Andric         else if (auto *Interface = dyn_cast<ObjCInterfaceDecl>(D))
14340b57cec5SDimitry Andric           ClassDeclared = Interface;
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric         assert(ClassDeclared && "cannot query interface");
14370b57cec5SDimitry Andric       } else {
14380b57cec5SDimitry Andric         if (IsArrow &&
14390b57cec5SDimitry Andric             IDecl->FindPropertyDeclaration(
14400b57cec5SDimitry Andric                 Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
14410b57cec5SDimitry Andric           S.Diag(MemberLoc, diag::err_property_found_suggest)
14420b57cec5SDimitry Andric               << Member << BaseExpr.get()->getType()
14430b57cec5SDimitry Andric               << FixItHint::CreateReplacement(OpLoc, ".");
14440b57cec5SDimitry Andric           return ExprError();
14450b57cec5SDimitry Andric         }
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric         S.Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
14480b57cec5SDimitry Andric             << IDecl->getDeclName() << MemberName
14490b57cec5SDimitry Andric             << BaseExpr.get()->getSourceRange();
14500b57cec5SDimitry Andric         return ExprError();
14510b57cec5SDimitry Andric       }
14520b57cec5SDimitry Andric     }
14530b57cec5SDimitry Andric 
14540b57cec5SDimitry Andric     assert(ClassDeclared);
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric     // If the decl being referenced had an error, return an error for this
14570b57cec5SDimitry Andric     // sub-expr without emitting another error, in order to avoid cascading
14580b57cec5SDimitry Andric     // error cases.
14590b57cec5SDimitry Andric     if (IV->isInvalidDecl())
14600b57cec5SDimitry Andric       return ExprError();
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric     // Check whether we can reference this field.
14630b57cec5SDimitry Andric     if (S.DiagnoseUseOfDecl(IV, MemberLoc))
14640b57cec5SDimitry Andric       return ExprError();
14650b57cec5SDimitry Andric     if (IV->getAccessControl() != ObjCIvarDecl::Public &&
14660b57cec5SDimitry Andric         IV->getAccessControl() != ObjCIvarDecl::Package) {
14670b57cec5SDimitry Andric       ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;
14680b57cec5SDimitry Andric       if (ObjCMethodDecl *MD = S.getCurMethodDecl())
14690b57cec5SDimitry Andric         ClassOfMethodDecl =  MD->getClassInterface();
14700b57cec5SDimitry Andric       else if (ObjCImpDecl && S.getCurFunctionDecl()) {
14710b57cec5SDimitry Andric         // Case of a c-function declared inside an objc implementation.
14720b57cec5SDimitry Andric         // FIXME: For a c-style function nested inside an objc implementation
14730b57cec5SDimitry Andric         // class, there is no implementation context available, so we pass
14740b57cec5SDimitry Andric         // down the context as argument to this routine. Ideally, this context
14750b57cec5SDimitry Andric         // need be passed down in the AST node and somehow calculated from the
14760b57cec5SDimitry Andric         // AST for a function decl.
14770b57cec5SDimitry Andric         if (ObjCImplementationDecl *IMPD =
14780b57cec5SDimitry Andric               dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))
14790b57cec5SDimitry Andric           ClassOfMethodDecl = IMPD->getClassInterface();
14800b57cec5SDimitry Andric         else if (ObjCCategoryImplDecl* CatImplClass =
14810b57cec5SDimitry Andric                    dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl))
14820b57cec5SDimitry Andric           ClassOfMethodDecl = CatImplClass->getClassInterface();
14830b57cec5SDimitry Andric       }
14840b57cec5SDimitry Andric       if (!S.getLangOpts().DebuggerSupport) {
14850b57cec5SDimitry Andric         if (IV->getAccessControl() == ObjCIvarDecl::Private) {
14860b57cec5SDimitry Andric           if (!declaresSameEntity(ClassDeclared, IDecl) ||
14870b57cec5SDimitry Andric               !declaresSameEntity(ClassOfMethodDecl, ClassDeclared))
14880b57cec5SDimitry Andric             S.Diag(MemberLoc, diag::err_private_ivar_access)
14890b57cec5SDimitry Andric               << IV->getDeclName();
14900b57cec5SDimitry Andric         } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
14910b57cec5SDimitry Andric           // @protected
14920b57cec5SDimitry Andric           S.Diag(MemberLoc, diag::err_protected_ivar_access)
14930b57cec5SDimitry Andric               << IV->getDeclName();
14940b57cec5SDimitry Andric       }
14950b57cec5SDimitry Andric     }
14960b57cec5SDimitry Andric     bool warn = true;
14970b57cec5SDimitry Andric     if (S.getLangOpts().ObjCWeak) {
14980b57cec5SDimitry Andric       Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts();
14990b57cec5SDimitry Andric       if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp))
15000b57cec5SDimitry Andric         if (UO->getOpcode() == UO_Deref)
15010b57cec5SDimitry Andric           BaseExp = UO->getSubExpr()->IgnoreParenCasts();
15020b57cec5SDimitry Andric 
15030b57cec5SDimitry Andric       if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp))
15040b57cec5SDimitry Andric         if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
15050b57cec5SDimitry Andric           S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access);
15060b57cec5SDimitry Andric           warn = false;
15070b57cec5SDimitry Andric         }
15080b57cec5SDimitry Andric     }
15090b57cec5SDimitry Andric     if (warn) {
15100b57cec5SDimitry Andric       if (ObjCMethodDecl *MD = S.getCurMethodDecl()) {
15110b57cec5SDimitry Andric         ObjCMethodFamily MF = MD->getMethodFamily();
15120fca6ea1SDimitry Andric         warn = (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
15130fca6ea1SDimitry Andric                 !S.ObjC().IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
15140b57cec5SDimitry Andric       }
15150b57cec5SDimitry Andric       if (warn)
15160b57cec5SDimitry Andric         S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
15170b57cec5SDimitry Andric     }
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric     ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr(
15200b57cec5SDimitry Andric         IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(),
15210b57cec5SDimitry Andric         IsArrow);
15220b57cec5SDimitry Andric 
15230b57cec5SDimitry Andric     if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
15240b57cec5SDimitry Andric       if (!S.isUnevaluatedContext() &&
15250b57cec5SDimitry Andric           !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
15260b57cec5SDimitry Andric         S.getCurFunction()->recordUseOfWeak(Result);
15270b57cec5SDimitry Andric     }
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric     return Result;
15300b57cec5SDimitry Andric   }
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric   // Objective-C property access.
15330b57cec5SDimitry Andric   const ObjCObjectPointerType *OPT;
15340b57cec5SDimitry Andric   if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {
15350b57cec5SDimitry Andric     if (!SS.isEmpty() && !SS.isInvalid()) {
15360b57cec5SDimitry Andric       S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
15370b57cec5SDimitry Andric           << 0 << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());
15380b57cec5SDimitry Andric       SS.clear();
15390b57cec5SDimitry Andric     }
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric     // This actually uses the base as an r-value.
15420b57cec5SDimitry Andric     BaseExpr = S.DefaultLvalueConversion(BaseExpr.get());
15430b57cec5SDimitry Andric     if (BaseExpr.isInvalid())
15440b57cec5SDimitry Andric       return ExprError();
15450b57cec5SDimitry Andric 
15460b57cec5SDimitry Andric     assert(S.Context.hasSameUnqualifiedType(BaseType,
15470b57cec5SDimitry Andric                                             BaseExpr.get()->getType()));
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric     IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric     const ObjCObjectType *OT = OPT->getObjectType();
15520b57cec5SDimitry Andric 
15530b57cec5SDimitry Andric     // id, with and without qualifiers.
15540b57cec5SDimitry Andric     if (OT->isObjCId()) {
15550b57cec5SDimitry Andric       // Check protocols on qualified interfaces.
15560b57cec5SDimitry Andric       Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
15570b57cec5SDimitry Andric       if (Decl *PMDecl =
15580b57cec5SDimitry Andric               FindGetterSetterNameDecl(OPT, Member, Sel, S.Context)) {
15590b57cec5SDimitry Andric         if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
15600b57cec5SDimitry Andric           // Check the use of this declaration
15610b57cec5SDimitry Andric           if (S.DiagnoseUseOfDecl(PD, MemberLoc))
15620b57cec5SDimitry Andric             return ExprError();
15630b57cec5SDimitry Andric 
15640b57cec5SDimitry Andric           return new (S.Context)
15650b57cec5SDimitry Andric               ObjCPropertyRefExpr(PD, S.Context.PseudoObjectTy, VK_LValue,
15660b57cec5SDimitry Andric                                   OK_ObjCProperty, MemberLoc, BaseExpr.get());
15670b57cec5SDimitry Andric         }
15680b57cec5SDimitry Andric 
15690b57cec5SDimitry Andric         if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
15700b57cec5SDimitry Andric           Selector SetterSel =
15710b57cec5SDimitry Andric             SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
15720b57cec5SDimitry Andric                                                    S.PP.getSelectorTable(),
15730b57cec5SDimitry Andric                                                    Member);
15740b57cec5SDimitry Andric           ObjCMethodDecl *SMD = nullptr;
15750b57cec5SDimitry Andric           if (Decl *SDecl = FindGetterSetterNameDecl(OPT,
15760b57cec5SDimitry Andric                                                      /*Property id*/ nullptr,
15770b57cec5SDimitry Andric                                                      SetterSel, S.Context))
15780b57cec5SDimitry Andric             SMD = dyn_cast<ObjCMethodDecl>(SDecl);
15790b57cec5SDimitry Andric 
15800b57cec5SDimitry Andric           return new (S.Context)
15810b57cec5SDimitry Andric               ObjCPropertyRefExpr(OMD, SMD, S.Context.PseudoObjectTy, VK_LValue,
15820b57cec5SDimitry Andric                                   OK_ObjCProperty, MemberLoc, BaseExpr.get());
15830b57cec5SDimitry Andric         }
15840b57cec5SDimitry Andric       }
15850b57cec5SDimitry Andric       // Use of id.member can only be for a property reference. Do not
15860b57cec5SDimitry Andric       // use the 'id' redefinition in this case.
15870b57cec5SDimitry Andric       if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr))
15880b57cec5SDimitry Andric         return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
15890b57cec5SDimitry Andric                                 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
15900b57cec5SDimitry Andric 
15910b57cec5SDimitry Andric       return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
15920b57cec5SDimitry Andric                          << MemberName << BaseType);
15930b57cec5SDimitry Andric     }
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric     // 'Class', unqualified only.
15960b57cec5SDimitry Andric     if (OT->isObjCClass()) {
15970b57cec5SDimitry Andric       // Only works in a method declaration (??!).
15980b57cec5SDimitry Andric       ObjCMethodDecl *MD = S.getCurMethodDecl();
15990b57cec5SDimitry Andric       if (!MD) {
16000b57cec5SDimitry Andric         if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
16010b57cec5SDimitry Andric           return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
16020b57cec5SDimitry Andric                                   ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric         goto fail;
16050b57cec5SDimitry Andric       }
16060b57cec5SDimitry Andric 
16070b57cec5SDimitry Andric       // Also must look for a getter name which uses property syntax.
16080b57cec5SDimitry Andric       Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);
16090b57cec5SDimitry Andric       ObjCInterfaceDecl *IFace = MD->getClassInterface();
16100b57cec5SDimitry Andric       if (!IFace)
16110b57cec5SDimitry Andric         goto fail;
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric       ObjCMethodDecl *Getter;
16140b57cec5SDimitry Andric       if ((Getter = IFace->lookupClassMethod(Sel))) {
16150b57cec5SDimitry Andric         // Check the use of this method.
16160b57cec5SDimitry Andric         if (S.DiagnoseUseOfDecl(Getter, MemberLoc))
16170b57cec5SDimitry Andric           return ExprError();
16180b57cec5SDimitry Andric       } else
16190b57cec5SDimitry Andric         Getter = IFace->lookupPrivateMethod(Sel, false);
16200b57cec5SDimitry Andric       // If we found a getter then this may be a valid dot-reference, we
16210b57cec5SDimitry Andric       // will look for the matching setter, in case it is needed.
16220b57cec5SDimitry Andric       Selector SetterSel =
16230b57cec5SDimitry Andric         SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
16240b57cec5SDimitry Andric                                                S.PP.getSelectorTable(),
16250b57cec5SDimitry Andric                                                Member);
16260b57cec5SDimitry Andric       ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
16270b57cec5SDimitry Andric       if (!Setter) {
16280b57cec5SDimitry Andric         // If this reference is in an @implementation, also check for 'private'
16290b57cec5SDimitry Andric         // methods.
16300b57cec5SDimitry Andric         Setter = IFace->lookupPrivateMethod(SetterSel, false);
16310b57cec5SDimitry Andric       }
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric       if (Setter && S.DiagnoseUseOfDecl(Setter, MemberLoc))
16340b57cec5SDimitry Andric         return ExprError();
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric       if (Getter || Setter) {
16370b57cec5SDimitry Andric         return new (S.Context) ObjCPropertyRefExpr(
16380b57cec5SDimitry Andric             Getter, Setter, S.Context.PseudoObjectTy, VK_LValue,
16390b57cec5SDimitry Andric             OK_ObjCProperty, MemberLoc, BaseExpr.get());
16400b57cec5SDimitry Andric       }
16410b57cec5SDimitry Andric 
16420b57cec5SDimitry Andric       if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))
16430b57cec5SDimitry Andric         return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
16440b57cec5SDimitry Andric                                 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
16450b57cec5SDimitry Andric 
16460b57cec5SDimitry Andric       return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
16470b57cec5SDimitry Andric                          << MemberName << BaseType);
16480b57cec5SDimitry Andric     }
16490b57cec5SDimitry Andric 
16500b57cec5SDimitry Andric     // Normal property access.
16510fca6ea1SDimitry Andric     return S.ObjC().HandleExprPropertyRefExpr(
16520fca6ea1SDimitry Andric         OPT, BaseExpr.get(), OpLoc, MemberName, MemberLoc, SourceLocation(),
16530fca6ea1SDimitry Andric         QualType(), false);
16540b57cec5SDimitry Andric   }
16550b57cec5SDimitry Andric 
165681ad6265SDimitry Andric   if (BaseType->isExtVectorBoolType()) {
165781ad6265SDimitry Andric     // We disallow element access for ext_vector_type bool.  There is no way to
165881ad6265SDimitry Andric     // materialize a reference to a vector element as a pointer (each element is
165981ad6265SDimitry Andric     // one bit in the vector).
166081ad6265SDimitry Andric     S.Diag(R.getNameLoc(), diag::err_ext_vector_component_name_illegal)
166181ad6265SDimitry Andric         << MemberName
166281ad6265SDimitry Andric         << (BaseExpr.get() ? BaseExpr.get()->getSourceRange() : SourceRange());
166381ad6265SDimitry Andric     return ExprError();
166481ad6265SDimitry Andric   }
166581ad6265SDimitry Andric 
16660b57cec5SDimitry Andric   // Handle 'field access' to vectors, such as 'V.xx'.
16670b57cec5SDimitry Andric   if (BaseType->isExtVectorType()) {
16680b57cec5SDimitry Andric     // FIXME: this expr should store IsArrow.
16690b57cec5SDimitry Andric     IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
1670bdd1243dSDimitry Andric     ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());
16710b57cec5SDimitry Andric     QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,
16720b57cec5SDimitry Andric                                            Member, MemberLoc);
16730b57cec5SDimitry Andric     if (ret.isNull())
16740b57cec5SDimitry Andric       return ExprError();
16750b57cec5SDimitry Andric     Qualifiers BaseQ =
16760b57cec5SDimitry Andric         S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers();
16770b57cec5SDimitry Andric     ret = S.Context.getQualifiedType(ret, BaseQ);
16780b57cec5SDimitry Andric 
16790b57cec5SDimitry Andric     return new (S.Context)
16800b57cec5SDimitry Andric         ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc);
16810b57cec5SDimitry Andric   }
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric   // Adjust builtin-sel to the appropriate redefinition type if that's
16840b57cec5SDimitry Andric   // not just a pointer to builtin-sel again.
16850b57cec5SDimitry Andric   if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&
16860b57cec5SDimitry Andric       !S.Context.getObjCSelRedefinitionType()->isObjCSelType()) {
16870b57cec5SDimitry Andric     BaseExpr = S.ImpCastExprToType(
16880b57cec5SDimitry Andric         BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast);
16890b57cec5SDimitry Andric     return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
16900b57cec5SDimitry Andric                             ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
16910b57cec5SDimitry Andric   }
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric   // Failure cases.
16940b57cec5SDimitry Andric  fail:
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric   // Recover from dot accesses to pointers, e.g.:
16970b57cec5SDimitry Andric   //   type *foo;
16980b57cec5SDimitry Andric   //   foo.bar
16990b57cec5SDimitry Andric   // This is actually well-formed in two cases:
17000b57cec5SDimitry Andric   //   - 'type' is an Objective C type
17010b57cec5SDimitry Andric   //   - 'bar' is a pseudo-destructor name which happens to refer to
17020b57cec5SDimitry Andric   //     the appropriate pointer type
17030b57cec5SDimitry Andric   if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
17040b57cec5SDimitry Andric     if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
17050b57cec5SDimitry Andric         MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
17060b57cec5SDimitry Andric       S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
17070b57cec5SDimitry Andric           << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
17080b57cec5SDimitry Andric           << FixItHint::CreateReplacement(OpLoc, "->");
17090b57cec5SDimitry Andric 
171004eeddc0SDimitry Andric       if (S.isSFINAEContext())
171104eeddc0SDimitry Andric         return ExprError();
171204eeddc0SDimitry Andric 
17130b57cec5SDimitry Andric       // Recurse as an -> access.
17140b57cec5SDimitry Andric       IsArrow = true;
17150b57cec5SDimitry Andric       return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
17160b57cec5SDimitry Andric                               ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
17170b57cec5SDimitry Andric     }
17180b57cec5SDimitry Andric   }
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric   // If the user is trying to apply -> or . to a function name, it's probably
17210b57cec5SDimitry Andric   // because they forgot parentheses to call that function.
17220b57cec5SDimitry Andric   if (S.tryToRecoverWithCall(
17230b57cec5SDimitry Andric           BaseExpr, S.PDiag(diag::err_member_reference_needs_call),
17240b57cec5SDimitry Andric           /*complain*/ false,
17250b57cec5SDimitry Andric           IsArrow ? &isPointerToRecordType : &isRecordType)) {
17260b57cec5SDimitry Andric     if (BaseExpr.isInvalid())
17270b57cec5SDimitry Andric       return ExprError();
17280b57cec5SDimitry Andric     BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get());
17290b57cec5SDimitry Andric     return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
17300b57cec5SDimitry Andric                             ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
17310b57cec5SDimitry Andric   }
17320b57cec5SDimitry Andric 
17335f757f3fSDimitry Andric   // HLSL supports implicit conversion of scalar types to single element vector
17345f757f3fSDimitry Andric   // rvalues in member expressions.
17355f757f3fSDimitry Andric   if (S.getLangOpts().HLSL && BaseType->isScalarType()) {
17365f757f3fSDimitry Andric     QualType VectorTy = S.Context.getExtVectorType(BaseType, 1);
17375f757f3fSDimitry Andric     BaseExpr = S.ImpCastExprToType(BaseExpr.get(), VectorTy, CK_VectorSplat,
17385f757f3fSDimitry Andric                                    BaseExpr.get()->getValueKind());
17395f757f3fSDimitry Andric     return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl,
17405f757f3fSDimitry Andric                             HasTemplateArgs, TemplateKWLoc);
17415f757f3fSDimitry Andric   }
17425f757f3fSDimitry Andric 
17430b57cec5SDimitry Andric   S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
17440b57cec5SDimitry Andric     << BaseType << BaseExpr.get()->getSourceRange() << MemberLoc;
17450b57cec5SDimitry Andric 
17460b57cec5SDimitry Andric   return ExprError();
17470b57cec5SDimitry Andric }
17480b57cec5SDimitry Andric 
17490b57cec5SDimitry Andric ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
17500b57cec5SDimitry Andric                                        SourceLocation OpLoc,
17510fca6ea1SDimitry Andric                                        tok::TokenKind OpKind, CXXScopeSpec &SS,
17520b57cec5SDimitry Andric                                        SourceLocation TemplateKWLoc,
17530fca6ea1SDimitry Andric                                        UnqualifiedId &Id, Decl *ObjCImpDecl) {
17540b57cec5SDimitry Andric   // Warn about the explicit constructor calls Microsoft extension.
17550b57cec5SDimitry Andric   if (getLangOpts().MicrosoftExt &&
17560b57cec5SDimitry Andric       Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
17570b57cec5SDimitry Andric     Diag(Id.getSourceRange().getBegin(),
17580b57cec5SDimitry Andric          diag::ext_ms_explicit_constructor_call);
17590b57cec5SDimitry Andric 
17600b57cec5SDimitry Andric   TemplateArgumentListInfo TemplateArgsBuffer;
17610b57cec5SDimitry Andric 
17620b57cec5SDimitry Andric   // Decompose the name into its component parts.
17630b57cec5SDimitry Andric   DeclarationNameInfo NameInfo;
17640b57cec5SDimitry Andric   const TemplateArgumentListInfo *TemplateArgs;
17650b57cec5SDimitry Andric   DecomposeUnqualifiedId(Id, TemplateArgsBuffer,
17660b57cec5SDimitry Andric                          NameInfo, TemplateArgs);
17670b57cec5SDimitry Andric 
17680b57cec5SDimitry Andric   bool IsArrow = (OpKind == tok::arrow);
17690b57cec5SDimitry Andric 
177081ad6265SDimitry Andric   if (getLangOpts().HLSL && IsArrow)
177181ad6265SDimitry Andric     return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2);
177281ad6265SDimitry Andric 
17730b57cec5SDimitry Andric   NamedDecl *FirstQualifierInScope
17740b57cec5SDimitry Andric     = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep()));
17750b57cec5SDimitry Andric 
17760b57cec5SDimitry Andric   // This is a postfix expression, so get rid of ParenListExprs.
17770b57cec5SDimitry Andric   ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
17780b57cec5SDimitry Andric   if (Result.isInvalid()) return ExprError();
17790b57cec5SDimitry Andric   Base = Result.get();
17800b57cec5SDimitry Andric 
17810b57cec5SDimitry Andric   ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
17820b57cec5SDimitry Andric   ExprResult Res = BuildMemberReferenceExpr(
17830b57cec5SDimitry Andric       Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc,
17840b57cec5SDimitry Andric       FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs);
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric   if (!Res.isInvalid() && isa<MemberExpr>(Res.get()))
17870b57cec5SDimitry Andric     CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get()));
17880b57cec5SDimitry Andric 
17890b57cec5SDimitry Andric   return Res;
17900b57cec5SDimitry Andric }
17910b57cec5SDimitry Andric 
17920b57cec5SDimitry Andric void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {
1793e8d8bef9SDimitry Andric   if (isUnevaluatedContext())
17940b57cec5SDimitry Andric     return;
17950b57cec5SDimitry Andric 
1796e8d8bef9SDimitry Andric   QualType ResultTy = E->getType();
1797e8d8bef9SDimitry Andric 
1798e8d8bef9SDimitry Andric   // Member accesses have four cases:
1799e8d8bef9SDimitry Andric   // 1: non-array member via "->": dereferences
1800e8d8bef9SDimitry Andric   // 2: non-array member via ".": nothing interesting happens
1801e8d8bef9SDimitry Andric   // 3: array member access via "->": nothing interesting happens
1802e8d8bef9SDimitry Andric   //    (this returns an array lvalue and does not actually dereference memory)
1803e8d8bef9SDimitry Andric   // 4: array member access via ".": *adds* a layer of indirection
1804e8d8bef9SDimitry Andric   if (ResultTy->isArrayType()) {
1805e8d8bef9SDimitry Andric     if (!E->isArrow()) {
1806e8d8bef9SDimitry Andric       // This might be something like:
1807e8d8bef9SDimitry Andric       //     (*structPtr).arrayMember
1808e8d8bef9SDimitry Andric       // which behaves roughly like:
1809e8d8bef9SDimitry Andric       //     &(*structPtr).pointerMember
1810e8d8bef9SDimitry Andric       // in that the apparent dereference in the base expression does not
1811e8d8bef9SDimitry Andric       // actually happen.
1812e8d8bef9SDimitry Andric       CheckAddressOfNoDeref(E->getBase());
1813e8d8bef9SDimitry Andric     }
1814e8d8bef9SDimitry Andric   } else if (E->isArrow()) {
18150b57cec5SDimitry Andric     if (const auto *Ptr = dyn_cast<PointerType>(
18160b57cec5SDimitry Andric             E->getBase()->getType().getDesugaredType(Context))) {
18170b57cec5SDimitry Andric       if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
18180b57cec5SDimitry Andric         ExprEvalContexts.back().PossibleDerefs.insert(E);
18190b57cec5SDimitry Andric     }
18200b57cec5SDimitry Andric   }
18210b57cec5SDimitry Andric }
18220b57cec5SDimitry Andric 
18230b57cec5SDimitry Andric ExprResult
18240b57cec5SDimitry Andric Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
18250b57cec5SDimitry Andric                               SourceLocation OpLoc, const CXXScopeSpec &SS,
18260b57cec5SDimitry Andric                               FieldDecl *Field, DeclAccessPair FoundDecl,
18270b57cec5SDimitry Andric                               const DeclarationNameInfo &MemberNameInfo) {
18280b57cec5SDimitry Andric   // x.a is an l-value if 'a' has a reference type. Otherwise:
18290b57cec5SDimitry Andric   // x.a is an l-value/x-value/pr-value if the base is (and note
18300b57cec5SDimitry Andric   //   that *x is always an l-value), except that if the base isn't
18310b57cec5SDimitry Andric   //   an ordinary object then we must have an rvalue.
18320b57cec5SDimitry Andric   ExprValueKind VK = VK_LValue;
18330b57cec5SDimitry Andric   ExprObjectKind OK = OK_Ordinary;
18340b57cec5SDimitry Andric   if (!IsArrow) {
18350b57cec5SDimitry Andric     if (BaseExpr->getObjectKind() == OK_Ordinary)
18360b57cec5SDimitry Andric       VK = BaseExpr->getValueKind();
18370b57cec5SDimitry Andric     else
1838fe6060f1SDimitry Andric       VK = VK_PRValue;
18390b57cec5SDimitry Andric   }
1840fe6060f1SDimitry Andric   if (VK != VK_PRValue && Field->isBitField())
18410b57cec5SDimitry Andric     OK = OK_BitField;
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric   // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
18440b57cec5SDimitry Andric   QualType MemberType = Field->getType();
18450b57cec5SDimitry Andric   if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
18460b57cec5SDimitry Andric     MemberType = Ref->getPointeeType();
18470b57cec5SDimitry Andric     VK = VK_LValue;
18480b57cec5SDimitry Andric   } else {
18490b57cec5SDimitry Andric     QualType BaseType = BaseExpr->getType();
1850fe6060f1SDimitry Andric     if (IsArrow) BaseType = BaseType->castAs<PointerType>()->getPointeeType();
18510b57cec5SDimitry Andric 
18520b57cec5SDimitry Andric     Qualifiers BaseQuals = BaseType.getQualifiers();
18530b57cec5SDimitry Andric 
18540b57cec5SDimitry Andric     // GC attributes are never picked up by members.
18550b57cec5SDimitry Andric     BaseQuals.removeObjCGCAttr();
18560b57cec5SDimitry Andric 
18570b57cec5SDimitry Andric     // CVR attributes from the base are picked up by members,
18580b57cec5SDimitry Andric     // except that 'mutable' members don't pick up 'const'.
18590b57cec5SDimitry Andric     if (Field->isMutable()) BaseQuals.removeConst();
18600b57cec5SDimitry Andric 
18610b57cec5SDimitry Andric     Qualifiers MemberQuals =
18620b57cec5SDimitry Andric         Context.getCanonicalType(MemberType).getQualifiers();
18630b57cec5SDimitry Andric 
18640b57cec5SDimitry Andric     assert(!MemberQuals.hasAddressSpace());
18650b57cec5SDimitry Andric 
18660b57cec5SDimitry Andric     Qualifiers Combined = BaseQuals + MemberQuals;
18670b57cec5SDimitry Andric     if (Combined != MemberQuals)
18680b57cec5SDimitry Andric       MemberType = Context.getQualifiedType(MemberType, Combined);
1869e8d8bef9SDimitry Andric 
1870e8d8bef9SDimitry Andric     // Pick up NoDeref from the base in case we end up using AddrOf on the
1871e8d8bef9SDimitry Andric     // result. E.g. the expression
1872e8d8bef9SDimitry Andric     //     &someNoDerefPtr->pointerMember
1873e8d8bef9SDimitry Andric     // should be a noderef pointer again.
1874e8d8bef9SDimitry Andric     if (BaseType->hasAttr(attr::NoDeref))
1875e8d8bef9SDimitry Andric       MemberType =
1876e8d8bef9SDimitry Andric           Context.getAttributedType(attr::NoDeref, MemberType, MemberType);
18770b57cec5SDimitry Andric   }
18780b57cec5SDimitry Andric 
18790b57cec5SDimitry Andric   auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
18800b57cec5SDimitry Andric   if (!(CurMethod && CurMethod->isDefaulted()))
18810b57cec5SDimitry Andric     UnusedPrivateFields.remove(Field);
18820b57cec5SDimitry Andric 
18830b57cec5SDimitry Andric   ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
18840b57cec5SDimitry Andric                                                   FoundDecl, Field);
18850b57cec5SDimitry Andric   if (Base.isInvalid())
18860b57cec5SDimitry Andric     return ExprError();
18870b57cec5SDimitry Andric 
18880b57cec5SDimitry Andric   // Build a reference to a private copy for non-static data members in
18890b57cec5SDimitry Andric   // non-static member functions, privatized by OpenMP constructs.
18900b57cec5SDimitry Andric   if (getLangOpts().OpenMP && IsArrow &&
18910b57cec5SDimitry Andric       !CurContext->isDependentContext() &&
18920b57cec5SDimitry Andric       isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
18930fca6ea1SDimitry Andric     if (auto *PrivateCopy = OpenMP().isOpenMPCapturedDecl(Field)) {
18940fca6ea1SDimitry Andric       return OpenMP().getOpenMPCapturedExpr(PrivateCopy, VK, OK,
18950b57cec5SDimitry Andric                                             MemberNameInfo.getLoc());
18960b57cec5SDimitry Andric     }
18970b57cec5SDimitry Andric   }
18980b57cec5SDimitry Andric 
18990fca6ea1SDimitry Andric   return BuildMemberExpr(
19000fca6ea1SDimitry Andric       Base.get(), IsArrow, OpLoc, SS.getWithLocInContext(Context),
19010b57cec5SDimitry Andric       /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,
19020fca6ea1SDimitry Andric       /*HadMultipleCandidates=*/false, MemberNameInfo, MemberType, VK, OK);
19030b57cec5SDimitry Andric }
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric ExprResult
19060b57cec5SDimitry Andric Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
19070b57cec5SDimitry Andric                               SourceLocation TemplateKWLoc,
19080b57cec5SDimitry Andric                               LookupResult &R,
19090b57cec5SDimitry Andric                               const TemplateArgumentListInfo *TemplateArgs,
19100b57cec5SDimitry Andric                               bool IsKnownInstance, const Scope *S) {
19110b57cec5SDimitry Andric   assert(!R.empty() && !R.isAmbiguous());
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric   SourceLocation loc = R.getNameLoc();
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric   // If this is known to be an instance access, go ahead and build an
19160b57cec5SDimitry Andric   // implicit 'this' expression now.
19170b57cec5SDimitry Andric   QualType ThisTy = getCurrentThisType();
19180b57cec5SDimitry Andric   assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
19190b57cec5SDimitry Andric 
19200b57cec5SDimitry Andric   Expr *baseExpr = nullptr; // null signifies implicit access
19210b57cec5SDimitry Andric   if (IsKnownInstance) {
19220b57cec5SDimitry Andric     SourceLocation Loc = R.getNameLoc();
19230b57cec5SDimitry Andric     if (SS.getRange().isValid())
19240b57cec5SDimitry Andric       Loc = SS.getRange().getBegin();
19250b57cec5SDimitry Andric     baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true);
19260b57cec5SDimitry Andric   }
19270b57cec5SDimitry Andric 
19285f757f3fSDimitry Andric   return BuildMemberReferenceExpr(
19295f757f3fSDimitry Andric       baseExpr, ThisTy,
19305f757f3fSDimitry Andric       /*OpLoc=*/SourceLocation(),
19315f757f3fSDimitry Andric       /*IsArrow=*/!getLangOpts().HLSL, SS, TemplateKWLoc,
19325f757f3fSDimitry Andric       /*FirstQualifierInScope=*/nullptr, R, TemplateArgs, S);
19330b57cec5SDimitry Andric }
1934