Path: blob/main/contrib/llvm-project/clang/lib/Sema/SemaExprMember.cpp
35233 views
//===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements semantic analysis member access expressions.9//10//===----------------------------------------------------------------------===//11#include "clang/AST/ASTLambda.h"12#include "clang/AST/DeclCXX.h"13#include "clang/AST/DeclObjC.h"14#include "clang/AST/DeclTemplate.h"15#include "clang/AST/ExprCXX.h"16#include "clang/AST/ExprObjC.h"17#include "clang/Lex/Preprocessor.h"18#include "clang/Sema/Lookup.h"19#include "clang/Sema/Overload.h"20#include "clang/Sema/Scope.h"21#include "clang/Sema/ScopeInfo.h"22#include "clang/Sema/SemaInternal.h"23#include "clang/Sema/SemaObjC.h"24#include "clang/Sema/SemaOpenMP.h"2526using namespace clang;27using namespace sema;2829typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet;3031/// Determines if the given class is provably not derived from all of32/// the prospective base classes.33static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record,34const BaseSet &Bases) {35auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) {36return !Bases.count(Base->getCanonicalDecl());37};38return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet);39}4041enum IMAKind {42/// The reference is definitely not an instance member access.43IMA_Static,4445/// The reference may be an implicit instance member access.46IMA_Mixed,4748/// The reference may be to an instance member, but it might be invalid if49/// so, because the context is not an instance method.50IMA_Mixed_StaticOrExplicitContext,5152/// The reference may be to an instance member, but it is invalid if53/// so, because the context is from an unrelated class.54IMA_Mixed_Unrelated,5556/// The reference is definitely an implicit instance member access.57IMA_Instance,5859/// The reference may be to an unresolved using declaration.60IMA_Unresolved,6162/// The reference is a contextually-permitted abstract member reference.63IMA_Abstract,6465/// Whether the context is static is dependent on the enclosing template (i.e.66/// in a dependent class scope explicit specialization).67IMA_Dependent,6869/// The reference may be to an unresolved using declaration and the70/// context is not an instance method.71IMA_Unresolved_StaticOrExplicitContext,7273// The reference refers to a field which is not a member of the containing74// class, which is allowed because we're in C++11 mode and the context is75// unevaluated.76IMA_Field_Uneval_Context,7778/// All possible referrents are instance members and the current79/// context is not an instance method.80IMA_Error_StaticOrExplicitContext,8182/// All possible referrents are instance members of an unrelated83/// class.84IMA_Error_Unrelated85};8687/// The given lookup names class member(s) and is not being used for88/// an address-of-member expression. Classify the type of access89/// according to whether it's possible that this reference names an90/// instance member. This is best-effort in dependent contexts; it is okay to91/// conservatively answer "yes", in which case some errors will simply92/// not be caught until template-instantiation.93static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,94const LookupResult &R) {95assert(!R.empty() && (*R.begin())->isCXXClassMember());9697DeclContext *DC = SemaRef.getFunctionLevelDeclContext();9899bool couldInstantiateToStatic = false;100bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull();101102if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) {103if (MD->isImplicitObjectMemberFunction()) {104isStaticOrExplicitContext = false;105// A dependent class scope function template explicit specialization106// that is neither declared 'static' nor with an explicit object107// parameter could instantiate to a static or non-static member function.108couldInstantiateToStatic = MD->getDependentSpecializationInfo();109}110}111112if (R.isUnresolvableResult()) {113if (couldInstantiateToStatic)114return IMA_Dependent;115return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext116: IMA_Unresolved;117}118119// Collect all the declaring classes of instance members we find.120bool hasNonInstance = false;121bool isField = false;122BaseSet Classes;123for (NamedDecl *D : R) {124// Look through any using decls.125D = D->getUnderlyingDecl();126127if (D->isCXXInstanceMember()) {128isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) ||129isa<IndirectFieldDecl>(D);130131CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());132Classes.insert(R->getCanonicalDecl());133} else134hasNonInstance = true;135}136137// If we didn't find any instance members, it can't be an implicit138// member reference.139if (Classes.empty())140return IMA_Static;141142if (couldInstantiateToStatic)143return IMA_Dependent;144145// C++11 [expr.prim.general]p12:146// An id-expression that denotes a non-static data member or non-static147// member function of a class can only be used:148// (...)149// - if that id-expression denotes a non-static data member and it150// appears in an unevaluated operand.151//152// This rule is specific to C++11. However, we also permit this form153// in unevaluated inline assembly operands, like the operand to a SIZE.154IMAKind AbstractInstanceResult = IMA_Static; // happens to be 'false'155assert(!AbstractInstanceResult);156switch (SemaRef.ExprEvalContexts.back().Context) {157case Sema::ExpressionEvaluationContext::Unevaluated:158case Sema::ExpressionEvaluationContext::UnevaluatedList:159if (isField && SemaRef.getLangOpts().CPlusPlus11)160AbstractInstanceResult = IMA_Field_Uneval_Context;161break;162163case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:164AbstractInstanceResult = IMA_Abstract;165break;166167case Sema::ExpressionEvaluationContext::DiscardedStatement:168case Sema::ExpressionEvaluationContext::ConstantEvaluated:169case Sema::ExpressionEvaluationContext::ImmediateFunctionContext:170case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:171case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:172break;173}174175// If the current context is not an instance method, it can't be176// an implicit member reference.177if (isStaticOrExplicitContext) {178if (hasNonInstance)179return IMA_Mixed_StaticOrExplicitContext;180181return AbstractInstanceResult ? AbstractInstanceResult182: IMA_Error_StaticOrExplicitContext;183}184185CXXRecordDecl *contextClass;186if (auto *MD = dyn_cast<CXXMethodDecl>(DC))187contextClass = MD->getParent()->getCanonicalDecl();188else if (auto *RD = dyn_cast<CXXRecordDecl>(DC))189contextClass = RD;190else191return AbstractInstanceResult ? AbstractInstanceResult192: IMA_Error_StaticOrExplicitContext;193194// [class.mfct.non-static]p3:195// ...is used in the body of a non-static member function of class X,196// if name lookup (3.4.1) resolves the name in the id-expression to a197// non-static non-type member of some class C [...]198// ...if C is not X or a base class of X, the class member access expression199// is ill-formed.200if (R.getNamingClass() &&201contextClass->getCanonicalDecl() !=202R.getNamingClass()->getCanonicalDecl()) {203// If the naming class is not the current context, this was a qualified204// member name lookup, and it's sufficient to check that we have the naming205// class as a base class.206Classes.clear();207Classes.insert(R.getNamingClass()->getCanonicalDecl());208}209210// If we can prove that the current context is unrelated to all the211// declaring classes, it can't be an implicit member reference (in212// which case it's an error if any of those members are selected).213if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes))214return hasNonInstance ? IMA_Mixed_Unrelated :215AbstractInstanceResult ? AbstractInstanceResult :216IMA_Error_Unrelated;217218return (hasNonInstance ? IMA_Mixed : IMA_Instance);219}220221/// Diagnose a reference to a field with no object available.222static void diagnoseInstanceReference(Sema &SemaRef,223const CXXScopeSpec &SS,224NamedDecl *Rep,225const DeclarationNameInfo &nameInfo) {226SourceLocation Loc = nameInfo.getLoc();227SourceRange Range(Loc);228if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());229230// Look through using shadow decls and aliases.231Rep = Rep->getUnderlyingDecl();232233DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();234CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);235CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;236CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());237238bool InStaticMethod = Method && Method->isStatic();239bool InExplicitObjectMethod =240Method && Method->isExplicitObjectMemberFunction();241bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep);242243std::string Replacement;244if (InExplicitObjectMethod) {245DeclarationName N = Method->getParamDecl(0)->getDeclName();246if (!N.isEmpty()) {247Replacement.append(N.getAsString());248Replacement.append(".");249}250}251if (IsField && InStaticMethod)252// "invalid use of member 'x' in static member function"253SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)254<< Range << nameInfo.getName() << /*static*/ 0;255else if (IsField && InExplicitObjectMethod) {256auto Diag = SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)257<< Range << nameInfo.getName() << /*explicit*/ 1;258if (!Replacement.empty())259Diag << FixItHint::CreateInsertion(Loc, Replacement);260} else if (ContextClass && RepClass && SS.isEmpty() &&261!InExplicitObjectMethod && !InStaticMethod &&262!RepClass->Equals(ContextClass) &&263RepClass->Encloses(ContextClass))264// Unqualified lookup in a non-static member function found a member of an265// enclosing class.266SemaRef.Diag(Loc, diag::err_nested_non_static_member_use)267<< IsField << RepClass << nameInfo.getName() << ContextClass << Range;268else if (IsField)269SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)270<< nameInfo.getName() << Range;271else if (!InExplicitObjectMethod)272SemaRef.Diag(Loc, diag::err_member_call_without_object)273<< Range << /*static*/ 0;274else {275if (const auto *Tpl = dyn_cast<FunctionTemplateDecl>(Rep))276Rep = Tpl->getTemplatedDecl();277const auto *Callee = cast<CXXMethodDecl>(Rep);278auto Diag = SemaRef.Diag(Loc, diag::err_member_call_without_object)279<< Range << Callee->isExplicitObjectMemberFunction();280if (!Replacement.empty())281Diag << FixItHint::CreateInsertion(Loc, Replacement);282}283}284285bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS,286LookupResult &R,287bool IsAddressOfOperand) {288if (!getLangOpts().CPlusPlus)289return false;290else if (R.empty() || !R.begin()->isCXXClassMember())291return false;292else if (!IsAddressOfOperand)293return true;294else if (!SS.isEmpty())295return false;296else if (R.isOverloadedResult())297return false;298else if (R.isUnresolvableResult())299return true;300else301return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl());302}303304ExprResult Sema::BuildPossibleImplicitMemberExpr(305const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,306const TemplateArgumentListInfo *TemplateArgs, const Scope *S) {307switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {308case IMA_Instance:309case IMA_Mixed:310case IMA_Mixed_Unrelated:311case IMA_Unresolved:312return BuildImplicitMemberExpr(313SS, TemplateKWLoc, R, TemplateArgs,314/*IsKnownInstance=*/Classification == IMA_Instance, S);315case IMA_Field_Uneval_Context:316Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)317<< R.getLookupNameInfo().getName();318[[fallthrough]];319case IMA_Static:320case IMA_Abstract:321case IMA_Mixed_StaticOrExplicitContext:322case IMA_Unresolved_StaticOrExplicitContext:323if (TemplateArgs || TemplateKWLoc.isValid())324return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,325TemplateArgs);326return BuildDeclarationNameExpr(SS, R, /*NeedsADL=*/false,327/*AcceptInvalidDecl=*/false);328case IMA_Dependent:329R.suppressDiagnostics();330return UnresolvedLookupExpr::Create(331Context, R.getNamingClass(), SS.getWithLocInContext(Context),332TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false,333TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true,334/*KnownInstantiationDependent=*/true);335336case IMA_Error_StaticOrExplicitContext:337case IMA_Error_Unrelated:338diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),339R.getLookupNameInfo());340return ExprError();341}342343llvm_unreachable("unexpected instance member access kind");344}345346/// Determine whether input char is from rgba component set.347static bool348IsRGBA(char c) {349switch (c) {350case 'r':351case 'g':352case 'b':353case 'a':354return true;355default:356return false;357}358}359360// OpenCL v1.1, s6.1.7361// The component swizzle length must be in accordance with the acceptable362// vector sizes.363static bool IsValidOpenCLComponentSwizzleLength(unsigned len)364{365return (len >= 1 && len <= 4) || len == 8 || len == 16;366}367368/// Check an ext-vector component access expression.369///370/// VK should be set in advance to the value kind of the base371/// expression.372static QualType373CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,374SourceLocation OpLoc, const IdentifierInfo *CompName,375SourceLocation CompLoc) {376// FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,377// see FIXME there.378//379// FIXME: This logic can be greatly simplified by splitting it along380// halving/not halving and reworking the component checking.381const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();382383// The vector accessor can't exceed the number of elements.384const char *compStr = CompName->getNameStart();385386// This flag determines whether or not the component is one of the four387// special names that indicate a subset of exactly half the elements are388// to be selected.389bool HalvingSwizzle = false;390391// This flag determines whether or not CompName has an 's' char prefix,392// indicating that it is a string of hex values to be used as vector indices.393bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1];394395bool HasRepeated = false;396bool HasIndex[16] = {};397398int Idx;399400// Check that we've found one of the special components, or that the component401// names must come from the same set.402if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||403!strcmp(compStr, "even") || !strcmp(compStr, "odd")) {404HalvingSwizzle = true;405} else if (!HexSwizzle &&406(Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {407bool HasRGBA = IsRGBA(*compStr);408do {409// Ensure that xyzw and rgba components don't intermingle.410if (HasRGBA != IsRGBA(*compStr))411break;412if (HasIndex[Idx]) HasRepeated = true;413HasIndex[Idx] = true;414compStr++;415} while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);416417// Emit a warning if an rgba selector is used earlier than OpenCL C 3.0.418if (HasRGBA || (*compStr && IsRGBA(*compStr))) {419if (S.getLangOpts().OpenCL &&420S.getLangOpts().getOpenCLCompatibleVersion() < 300) {421const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr;422S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector)423<< StringRef(DiagBegin, 1) << SourceRange(CompLoc);424}425}426} else {427if (HexSwizzle) compStr++;428while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {429if (HasIndex[Idx]) HasRepeated = true;430HasIndex[Idx] = true;431compStr++;432}433}434435if (!HalvingSwizzle && *compStr) {436// We didn't get to the end of the string. This means the component names437// didn't come from the same set *or* we encountered an illegal name.438S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal)439<< StringRef(compStr, 1) << SourceRange(CompLoc);440return QualType();441}442443// Ensure no component accessor exceeds the width of the vector type it444// operates on.445if (!HalvingSwizzle) {446compStr = CompName->getNameStart();447448if (HexSwizzle)449compStr++;450451while (*compStr) {452if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) {453S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)454<< baseType << SourceRange(CompLoc);455return QualType();456}457}458}459460// OpenCL mode requires swizzle length to be in accordance with accepted461// sizes. Clang however supports arbitrary lengths for other languages.462if (S.getLangOpts().OpenCL && !HalvingSwizzle) {463unsigned SwizzleLength = CompName->getLength();464465if (HexSwizzle)466SwizzleLength--;467468if (IsValidOpenCLComponentSwizzleLength(SwizzleLength) == false) {469S.Diag(OpLoc, diag::err_opencl_ext_vector_component_invalid_length)470<< SwizzleLength << SourceRange(CompLoc);471return QualType();472}473}474475// The component accessor looks fine - now we need to compute the actual type.476// The vector type is implied by the component accessor. For example,477// vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc.478// vec4.s0 is a float, vec4.s23 is a vec3, etc.479// vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2.480unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2481: CompName->getLength();482if (HexSwizzle)483CompSize--;484485if (CompSize == 1)486return vecType->getElementType();487488if (HasRepeated)489VK = VK_PRValue;490491QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);492// Now look up the TypeDefDecl from the vector type. Without this,493// diagostics look bad. We want extended vector types to appear built-in.494for (Sema::ExtVectorDeclsType::iterator495I = S.ExtVectorDecls.begin(S.getExternalSource()),496E = S.ExtVectorDecls.end();497I != E; ++I) {498if ((*I)->getUnderlyingType() == VT)499return S.Context.getTypedefType(*I);500}501502return VT; // should never get here (a typedef type should always be found).503}504505static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,506IdentifierInfo *Member,507const Selector &Sel,508ASTContext &Context) {509if (Member)510if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(511Member, ObjCPropertyQueryKind::OBJC_PR_query_instance))512return PD;513if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))514return OMD;515516for (const auto *I : PDecl->protocols()) {517if (Decl *D = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel,518Context))519return D;520}521return nullptr;522}523524static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,525IdentifierInfo *Member,526const Selector &Sel,527ASTContext &Context) {528// Check protocols on qualified interfaces.529Decl *GDecl = nullptr;530for (const auto *I : QIdTy->quals()) {531if (Member)532if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(533Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {534GDecl = PD;535break;536}537// Also must look for a getter or setter name which uses property syntax.538if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) {539GDecl = OMD;540break;541}542}543if (!GDecl) {544for (const auto *I : QIdTy->quals()) {545// Search in the protocol-qualifier list of current protocol.546GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context);547if (GDecl)548return GDecl;549}550}551return GDecl;552}553554ExprResult555Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,556bool IsArrow, SourceLocation OpLoc,557const CXXScopeSpec &SS,558SourceLocation TemplateKWLoc,559NamedDecl *FirstQualifierInScope,560const DeclarationNameInfo &NameInfo,561const TemplateArgumentListInfo *TemplateArgs) {562// Even in dependent contexts, try to diagnose base expressions with563// obviously wrong types, e.g.:564//565// T* t;566// t.f;567//568// In Obj-C++, however, the above expression is valid, since it could be569// accessing the 'f' property if T is an Obj-C interface. The extra check570// allows this, while still reporting an error if T is a struct pointer.571if (!IsArrow) {572const PointerType *PT = BaseType->getAs<PointerType>();573if (PT && (!getLangOpts().ObjC ||574PT->getPointeeType()->isRecordType())) {575assert(BaseExpr && "cannot happen with implicit member accesses");576Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)577<< BaseType << BaseExpr->getSourceRange() << NameInfo.getSourceRange();578return ExprError();579}580}581582assert(BaseType->isDependentType() || NameInfo.getName().isDependentName() ||583isDependentScopeSpecifier(SS) ||584(TemplateArgs && llvm::any_of(TemplateArgs->arguments(),585[](const TemplateArgumentLoc &Arg) {586return Arg.getArgument().isDependent();587})));588589// Get the type being accessed in BaseType. If this is an arrow, the BaseExpr590// must have pointer type, and the accessed type is the pointee.591return CXXDependentScopeMemberExpr::Create(592Context, BaseExpr, BaseType, IsArrow, OpLoc,593SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope,594NameInfo, TemplateArgs);595}596597/// We know that the given qualified member reference points only to598/// declarations which do not belong to the static type of the base599/// expression. Diagnose the problem.600static void DiagnoseQualifiedMemberReference(Sema &SemaRef,601Expr *BaseExpr,602QualType BaseType,603const CXXScopeSpec &SS,604NamedDecl *rep,605const DeclarationNameInfo &nameInfo) {606// If this is an implicit member access, use a different set of607// diagnostics.608if (!BaseExpr)609return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo);610611SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)612<< SS.getRange() << rep << BaseType;613}614615bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,616QualType BaseType,617const CXXScopeSpec &SS,618const LookupResult &R) {619CXXRecordDecl *BaseRecord =620cast_or_null<CXXRecordDecl>(computeDeclContext(BaseType));621if (!BaseRecord) {622// We can't check this yet because the base type is still623// dependent.624assert(BaseType->isDependentType());625return false;626}627628for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {629// If this is an implicit member reference and we find a630// non-instance member, it's not an error.631if (!BaseExpr && !(*I)->isCXXInstanceMember())632return false;633634// Note that we use the DC of the decl, not the underlying decl.635DeclContext *DC = (*I)->getDeclContext()->getNonTransparentContext();636if (!DC->isRecord())637continue;638639CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl();640if (BaseRecord->getCanonicalDecl() == MemberRecord ||641!BaseRecord->isProvablyNotDerivedFrom(MemberRecord))642return false;643}644645DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS,646R.getRepresentativeDecl(),647R.getLookupNameInfo());648return true;649}650651namespace {652653// Callback to only accept typo corrections that are either a ValueDecl or a654// FunctionTemplateDecl and are declared in the current record or, for a C++655// classes, one of its base classes.656class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {657public:658explicit RecordMemberExprValidatorCCC(QualType RTy)659: Record(RTy->getAsRecordDecl()) {660// Don't add bare keywords to the consumer since they will always fail661// validation by virtue of not being associated with any decls.662WantTypeSpecifiers = false;663WantExpressionKeywords = false;664WantCXXNamedCasts = false;665WantFunctionLikeCasts = false;666WantRemainingKeywords = false;667}668669bool ValidateCandidate(const TypoCorrection &candidate) override {670NamedDecl *ND = candidate.getCorrectionDecl();671// Don't accept candidates that cannot be member functions, constants,672// variables, or templates.673if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)))674return false;675676// Accept candidates that occur in the current record.677if (Record->containsDecl(ND))678return true;679680if (const auto *RD = dyn_cast<CXXRecordDecl>(Record)) {681// Accept candidates that occur in any of the current class' base classes.682for (const auto &BS : RD->bases()) {683if (const auto *BSTy = BS.getType()->getAs<RecordType>()) {684if (BSTy->getDecl()->containsDecl(ND))685return true;686}687}688}689690return false;691}692693std::unique_ptr<CorrectionCandidateCallback> clone() override {694return std::make_unique<RecordMemberExprValidatorCCC>(*this);695}696697private:698const RecordDecl *const Record;699};700701}702703static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,704Expr *BaseExpr, QualType RTy,705SourceLocation OpLoc, bool IsArrow,706CXXScopeSpec &SS, bool HasTemplateArgs,707SourceLocation TemplateKWLoc,708TypoExpr *&TE) {709SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();710if (!RTy->isDependentType() &&711!SemaRef.isThisOutsideMemberFunctionBody(RTy) &&712SemaRef.RequireCompleteType(713OpLoc, RTy, diag::err_typecheck_incomplete_tag, BaseRange))714return true;715716// LookupTemplateName/LookupParsedName don't expect these both to exist717// simultaneously.718QualType ObjectType = SS.isSet() ? QualType() : RTy;719if (HasTemplateArgs || TemplateKWLoc.isValid())720return SemaRef.LookupTemplateName(R,721/*S=*/nullptr, SS, ObjectType,722/*EnteringContext=*/false, TemplateKWLoc);723724SemaRef.LookupParsedName(R, /*S=*/nullptr, &SS, ObjectType);725726if (!R.empty() || R.wasNotFoundInCurrentInstantiation())727return false;728729DeclarationName Typo = R.getLookupName();730SourceLocation TypoLoc = R.getNameLoc();731// Recompute the lookup context.732DeclContext *DC = SS.isSet() ? SemaRef.computeDeclContext(SS)733: SemaRef.computeDeclContext(RTy);734735struct QueryState {736Sema &SemaRef;737DeclarationNameInfo NameInfo;738Sema::LookupNameKind LookupKind;739RedeclarationKind Redecl;740};741QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),742R.redeclarationKind()};743RecordMemberExprValidatorCCC CCC(RTy);744TE = SemaRef.CorrectTypoDelayed(745R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC,746[=, &SemaRef](const TypoCorrection &TC) {747if (TC) {748assert(!TC.isKeyword() &&749"Got a keyword as a correction for a member!");750bool DroppedSpecifier =751TC.WillReplaceSpecifier() &&752Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts());753SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)754<< Typo << DC << DroppedSpecifier755<< SS.getRange());756} else {757SemaRef.Diag(TypoLoc, diag::err_no_member)758<< Typo << DC << (SS.isSet() ? SS.getRange() : BaseRange);759}760},761[=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {762LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl);763R.clear(); // Ensure there's no decls lingering in the shared state.764R.suppressDiagnostics();765R.setLookupName(TC.getCorrection());766for (NamedDecl *ND : TC)767R.addDecl(ND);768R.resolveKind();769return SemaRef.BuildMemberReferenceExpr(770BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),771nullptr, R, nullptr, nullptr);772},773Sema::CTK_ErrorRecovery, DC);774775return false;776}777778static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,779ExprResult &BaseExpr, bool &IsArrow,780SourceLocation OpLoc, CXXScopeSpec &SS,781Decl *ObjCImpDecl, bool HasTemplateArgs,782SourceLocation TemplateKWLoc);783784ExprResult Sema::BuildMemberReferenceExpr(785Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,786CXXScopeSpec &SS, SourceLocation TemplateKWLoc,787NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,788const TemplateArgumentListInfo *TemplateArgs, const Scope *S,789ActOnMemberAccessExtraArgs *ExtraArgs) {790LookupResult R(*this, NameInfo, LookupMemberName);791792// Implicit member accesses.793if (!Base) {794TypoExpr *TE = nullptr;795QualType RecordTy = BaseType;796if (IsArrow) RecordTy = RecordTy->castAs<PointerType>()->getPointeeType();797if (LookupMemberExprInRecord(*this, R, nullptr, RecordTy, OpLoc, IsArrow,798SS, TemplateArgs != nullptr, TemplateKWLoc,799TE))800return ExprError();801if (TE)802return TE;803804// Explicit member accesses.805} else {806ExprResult BaseResult = Base;807ExprResult Result =808LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS,809ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,810TemplateArgs != nullptr, TemplateKWLoc);811812if (BaseResult.isInvalid())813return ExprError();814Base = BaseResult.get();815816if (Result.isInvalid())817return ExprError();818819if (Result.get())820return Result;821822// LookupMemberExpr can modify Base, and thus change BaseType823BaseType = Base->getType();824}825826// BuildMemberReferenceExpr expects the nested-name-specifier, if any, to be827// valid.828if (SS.isInvalid())829return ExprError();830831return BuildMemberReferenceExpr(Base, BaseType,832OpLoc, IsArrow, SS, TemplateKWLoc,833FirstQualifierInScope, R, TemplateArgs, S,834false, ExtraArgs);835}836837ExprResult838Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,839SourceLocation loc,840IndirectFieldDecl *indirectField,841DeclAccessPair foundDecl,842Expr *baseObjectExpr,843SourceLocation opLoc) {844// First, build the expression that refers to the base object.845846// Case 1: the base of the indirect field is not a field.847VarDecl *baseVariable = indirectField->getVarDecl();848CXXScopeSpec EmptySS;849if (baseVariable) {850assert(baseVariable->getType()->isRecordType());851852// In principle we could have a member access expression that853// accesses an anonymous struct/union that's a static member of854// the base object's class. However, under the current standard,855// static data members cannot be anonymous structs or unions.856// Supporting this is as easy as building a MemberExpr here.857assert(!baseObjectExpr && "anonymous struct/union is static data member?");858859DeclarationNameInfo baseNameInfo(DeclarationName(), loc);860861ExprResult result862= BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);863if (result.isInvalid()) return ExprError();864865baseObjectExpr = result.get();866}867868assert((baseVariable || baseObjectExpr) &&869"referencing anonymous struct/union without a base variable or "870"expression");871872// Build the implicit member references to the field of the873// anonymous struct/union.874Expr *result = baseObjectExpr;875IndirectFieldDecl::chain_iterator876FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();877878// Case 2: the base of the indirect field is a field and the user879// wrote a member expression.880if (!baseVariable) {881FieldDecl *field = cast<FieldDecl>(*FI);882883bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType();884885// Make a nameInfo that properly uses the anonymous name.886DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);887888// Build the first member access in the chain with full information.889result =890BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(),891SS, field, foundDecl, memberNameInfo)892.get();893if (!result)894return ExprError();895}896897// In all cases, we should now skip the first declaration in the chain.898++FI;899900while (FI != FEnd) {901FieldDecl *field = cast<FieldDecl>(*FI++);902903// FIXME: these are somewhat meaningless904DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);905DeclAccessPair fakeFoundDecl =906DeclAccessPair::make(field, field->getAccess());907908result =909BuildFieldReferenceExpr(result, /*isarrow*/ false, SourceLocation(),910(FI == FEnd ? SS : EmptySS), field,911fakeFoundDecl, memberNameInfo)912.get();913}914915return result;916}917918static ExprResult919BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,920const CXXScopeSpec &SS,921MSPropertyDecl *PD,922const DeclarationNameInfo &NameInfo) {923// Property names are always simple identifiers and therefore never924// require any interesting additional storage.925return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,926S.Context.PseudoObjectTy, VK_LValue,927SS.getWithLocInContext(S.Context),928NameInfo.getLoc());929}930931MemberExpr *Sema::BuildMemberExpr(932Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS,933SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,934bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,935QualType Ty, ExprValueKind VK, ExprObjectKind OK,936const TemplateArgumentListInfo *TemplateArgs) {937assert((!IsArrow || Base->isPRValue()) &&938"-> base must be a pointer prvalue");939MemberExpr *E =940MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc,941Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty,942VK, OK, getNonOdrUseReasonInCurrentContext(Member));943E->setHadMultipleCandidates(HadMultipleCandidates);944MarkMemberReferenced(E);945946// C++ [except.spec]p17:947// An exception-specification is considered to be needed when:948// - in an expression the function is the unique lookup result or the949// selected member of a set of overloaded functions950if (auto *FPT = Ty->getAs<FunctionProtoType>()) {951if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {952if (auto *NewFPT = ResolveExceptionSpec(MemberNameInfo.getLoc(), FPT))953E->setType(Context.getQualifiedType(NewFPT, Ty.getQualifiers()));954}955}956957return E;958}959960/// Determine if the given scope is within a function-try-block handler.961static bool IsInFnTryBlockHandler(const Scope *S) {962// Walk the scope stack until finding a FnTryCatchScope, or leave the963// function scope. If a FnTryCatchScope is found, check whether the TryScope964// flag is set. If it is not, it's a function-try-block handler.965for (; S != S->getFnParent(); S = S->getParent()) {966if (S->isFnTryCatchScope())967return (S->getFlags() & Scope::TryScope) != Scope::TryScope;968}969return false;970}971972ExprResult973Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,974SourceLocation OpLoc, bool IsArrow,975const CXXScopeSpec &SS,976SourceLocation TemplateKWLoc,977NamedDecl *FirstQualifierInScope,978LookupResult &R,979const TemplateArgumentListInfo *TemplateArgs,980const Scope *S,981bool SuppressQualifierCheck,982ActOnMemberAccessExtraArgs *ExtraArgs) {983assert(!SS.isInvalid() && "nested-name-specifier cannot be invalid");984// If the member wasn't found in the current instantiation, or if the985// arrow operator was used with a dependent non-pointer object expression,986// build a CXXDependentScopeMemberExpr.987if (R.wasNotFoundInCurrentInstantiation() ||988(R.getLookupName().getCXXOverloadedOperator() == OO_Equal &&989(SS.isSet() ? SS.getScopeRep()->isDependent()990: BaseExprType->isDependentType())))991return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS,992TemplateKWLoc, FirstQualifierInScope,993R.getLookupNameInfo(), TemplateArgs);994995QualType BaseType = BaseExprType;996if (IsArrow) {997assert(BaseType->isPointerType());998BaseType = BaseType->castAs<PointerType>()->getPointeeType();999}1000R.setBaseObjectType(BaseType);10011002assert((SS.isEmpty()1003? !BaseType->isDependentType() || computeDeclContext(BaseType)1004: !isDependentScopeSpecifier(SS) || computeDeclContext(SS)) &&1005"dependent lookup context that isn't the current instantiation?");10061007// C++1z [expr.ref]p2:1008// For the first option (dot) the first expression shall be a glvalue [...]1009if (!IsArrow && BaseExpr && BaseExpr->isPRValue()) {1010ExprResult Converted = TemporaryMaterializationConversion(BaseExpr);1011if (Converted.isInvalid())1012return ExprError();1013BaseExpr = Converted.get();1014}10151016const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();1017DeclarationName MemberName = MemberNameInfo.getName();1018SourceLocation MemberLoc = MemberNameInfo.getLoc();10191020if (R.isAmbiguous())1021return ExprError();10221023// [except.handle]p10: Referring to any non-static member or base class of an1024// object in the handler for a function-try-block of a constructor or1025// destructor for that object results in undefined behavior.1026const auto *FD = getCurFunctionDecl();1027if (S && BaseExpr && FD &&1028(isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&1029isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) &&1030IsInFnTryBlockHandler(S))1031Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr)1032<< isa<CXXDestructorDecl>(FD);10331034if (R.empty()) {1035ExprResult RetryExpr = ExprError();1036if (ExtraArgs && !IsArrow && BaseExpr && !BaseExpr->isTypeDependent()) {1037SFINAETrap Trap(*this, true);1038ParsedType ObjectType;1039bool MayBePseudoDestructor = false;1040RetryExpr = ActOnStartCXXMemberReference(getCurScope(), BaseExpr, OpLoc,1041tok::arrow, ObjectType,1042MayBePseudoDestructor);1043if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {1044CXXScopeSpec TempSS(SS);1045RetryExpr = ActOnMemberAccessExpr(1046ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,1047TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);1048}1049if (Trap.hasErrorOccurred())1050RetryExpr = ExprError();1051}10521053// Rederive where we looked up.1054DeclContext *DC =1055(SS.isSet() ? computeDeclContext(SS) : computeDeclContext(BaseType));1056assert(DC);10571058if (RetryExpr.isUsable())1059Diag(OpLoc, diag::err_no_member_overloaded_arrow)1060<< MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->");1061else1062Diag(R.getNameLoc(), diag::err_no_member)1063<< MemberName << DC1064<< (SS.isSet()1065? SS.getRange()1066: (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()));1067return RetryExpr;1068}10691070// Diagnose lookups that find only declarations from a non-base1071// type. This is possible for either qualified lookups (which may1072// have been qualified with an unrelated type) or implicit member1073// expressions (which were found with unqualified lookup and thus1074// may have come from an enclosing scope). Note that it's okay for1075// lookup to find declarations from a non-base type as long as those1076// aren't the ones picked by overload resolution.1077if ((SS.isSet() || !BaseExpr ||1078(isa<CXXThisExpr>(BaseExpr) &&1079cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&1080!SuppressQualifierCheck &&1081CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))1082return ExprError();10831084// Construct an unresolved result if we in fact got an unresolved1085// result.1086if (R.isOverloadedResult() || R.isUnresolvableResult()) {1087// Suppress any lookup-related diagnostics; we'll do these when we1088// pick a member.1089R.suppressDiagnostics();10901091UnresolvedMemberExpr *MemExpr1092= UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(),1093BaseExpr, BaseExprType,1094IsArrow, OpLoc,1095SS.getWithLocInContext(Context),1096TemplateKWLoc, MemberNameInfo,1097TemplateArgs, R.begin(), R.end());10981099return MemExpr;1100}11011102assert(R.isSingleResult());1103DeclAccessPair FoundDecl = R.begin().getPair();1104NamedDecl *MemberDecl = R.getFoundDecl();11051106// FIXME: diagnose the presence of template arguments now.11071108// If the decl being referenced had an error, return an error for this1109// sub-expr without emitting another error, in order to avoid cascading1110// error cases.1111if (MemberDecl->isInvalidDecl())1112return ExprError();11131114// Handle the implicit-member-access case.1115if (!BaseExpr) {1116// If this is not an instance member, convert to a non-member access.1117if (!MemberDecl->isCXXInstanceMember()) {1118// We might have a variable template specialization (or maybe one day a1119// member concept-id).1120if (TemplateArgs || TemplateKWLoc.isValid())1121return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/false, TemplateArgs);11221123return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl,1124FoundDecl, TemplateArgs);1125}1126SourceLocation Loc = R.getNameLoc();1127if (SS.getRange().isValid())1128Loc = SS.getRange().getBegin();1129BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true);1130}11311132// Check the use of this member.1133if (DiagnoseUseOfDecl(MemberDecl, MemberLoc))1134return ExprError();11351136if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))1137return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl,1138MemberNameInfo);11391140if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl))1141return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD,1142MemberNameInfo);11431144if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))1145// We may have found a field within an anonymous union or struct1146// (C++ [class.union]).1147return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,1148FoundDecl, BaseExpr,1149OpLoc);11501151if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {1152return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,1153SS.getWithLocInContext(Context), TemplateKWLoc, Var,1154FoundDecl, /*HadMultipleCandidates=*/false,1155MemberNameInfo, Var->getType().getNonReferenceType(),1156VK_LValue, OK_Ordinary);1157}11581159if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {1160ExprValueKind valueKind;1161QualType type;1162if (MemberFn->isInstance()) {1163valueKind = VK_PRValue;1164type = Context.BoundMemberTy;1165} else {1166valueKind = VK_LValue;1167type = MemberFn->getType();1168}11691170return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,1171SS.getWithLocInContext(Context), TemplateKWLoc,1172MemberFn, FoundDecl, /*HadMultipleCandidates=*/false,1173MemberNameInfo, type, valueKind, OK_Ordinary);1174}1175assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");11761177if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {1178return BuildMemberExpr(1179BaseExpr, IsArrow, OpLoc, SS.getWithLocInContext(Context),1180TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandidates=*/false,1181MemberNameInfo, Enum->getType(), VK_PRValue, OK_Ordinary);1182}11831184if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {1185if (!TemplateArgs) {1186diagnoseMissingTemplateArguments(1187SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc);1188return ExprError();1189}11901191DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc,1192MemberNameInfo.getLoc(), *TemplateArgs);1193if (VDecl.isInvalid())1194return ExprError();11951196// Non-dependent member, but dependent template arguments.1197if (!VDecl.get())1198return ActOnDependentMemberExpr(1199BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc,1200FirstQualifierInScope, MemberNameInfo, TemplateArgs);12011202VarDecl *Var = cast<VarDecl>(VDecl.get());1203if (!Var->getTemplateSpecializationKind())1204Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc);12051206return BuildMemberExpr(BaseExpr, IsArrow, OpLoc,1207SS.getWithLocInContext(Context), TemplateKWLoc, Var,1208FoundDecl, /*HadMultipleCandidates=*/false,1209MemberNameInfo, Var->getType().getNonReferenceType(),1210VK_LValue, OK_Ordinary, TemplateArgs);1211}12121213// We found something that we didn't expect. Complain.1214if (isa<TypeDecl>(MemberDecl))1215Diag(MemberLoc, diag::err_typecheck_member_reference_type)1216<< MemberName << BaseType << int(IsArrow);1217else1218Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)1219<< MemberName << BaseType << int(IsArrow);12201221Diag(MemberDecl->getLocation(), diag::note_member_declared_here)1222<< MemberName;1223R.suppressDiagnostics();1224return ExprError();1225}12261227/// Given that normal member access failed on the given expression,1228/// and given that the expression's type involves builtin-id or1229/// builtin-Class, decide whether substituting in the redefinition1230/// types would be profitable. The redefinition type is whatever1231/// this translation unit tried to typedef to id/Class; we store1232/// it to the side and then re-use it in places like this.1233static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) {1234const ObjCObjectPointerType *opty1235= base.get()->getType()->getAs<ObjCObjectPointerType>();1236if (!opty) return false;12371238const ObjCObjectType *ty = opty->getObjectType();12391240QualType redef;1241if (ty->isObjCId()) {1242redef = S.Context.getObjCIdRedefinitionType();1243} else if (ty->isObjCClass()) {1244redef = S.Context.getObjCClassRedefinitionType();1245} else {1246return false;1247}12481249// Do the substitution as long as the redefinition type isn't just a1250// possibly-qualified pointer to builtin-id or builtin-Class again.1251opty = redef->getAs<ObjCObjectPointerType>();1252if (opty && !opty->getObjectType()->getInterface())1253return false;12541255base = S.ImpCastExprToType(base.get(), redef, CK_BitCast);1256return true;1257}12581259static bool isRecordType(QualType T) {1260return T->isRecordType();1261}1262static bool isPointerToRecordType(QualType T) {1263if (const PointerType *PT = T->getAs<PointerType>())1264return PT->getPointeeType()->isRecordType();1265return false;1266}12671268ExprResult1269Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {1270if (IsArrow && !Base->getType()->isFunctionType())1271return DefaultFunctionArrayLvalueConversion(Base);12721273return CheckPlaceholderExpr(Base);1274}12751276/// Look up the given member of the given non-type-dependent1277/// expression. This can return in one of two ways:1278/// * If it returns a sentinel null-but-valid result, the caller will1279/// assume that lookup was performed and the results written into1280/// the provided structure. It will take over from there.1281/// * Otherwise, the returned expression will be produced in place of1282/// an ordinary member expression.1283///1284/// The ObjCImpDecl bit is a gross hack that will need to be properly1285/// fixed for ObjC++.1286static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,1287ExprResult &BaseExpr, bool &IsArrow,1288SourceLocation OpLoc, CXXScopeSpec &SS,1289Decl *ObjCImpDecl, bool HasTemplateArgs,1290SourceLocation TemplateKWLoc) {1291assert(BaseExpr.get() && "no base expression");12921293// Perform default conversions.1294BaseExpr = S.PerformMemberExprBaseConversion(BaseExpr.get(), IsArrow);1295if (BaseExpr.isInvalid())1296return ExprError();12971298QualType BaseType = BaseExpr.get()->getType();12991300DeclarationName MemberName = R.getLookupName();1301SourceLocation MemberLoc = R.getNameLoc();13021303// For later type-checking purposes, turn arrow accesses into dot1304// accesses. The only access type we support that doesn't follow1305// the C equivalence "a->b === (*a).b" is ObjC property accesses,1306// and those never use arrows, so this is unaffected.1307if (IsArrow) {1308if (const PointerType *Ptr = BaseType->getAs<PointerType>())1309BaseType = Ptr->getPointeeType();1310else if (const ObjCObjectPointerType *Ptr =1311BaseType->getAs<ObjCObjectPointerType>())1312BaseType = Ptr->getPointeeType();1313else if (BaseType->isFunctionType())1314goto fail;1315else if (BaseType->isDependentType())1316BaseType = S.Context.DependentTy;1317else if (BaseType->isRecordType()) {1318// Recover from arrow accesses to records, e.g.:1319// struct MyRecord foo;1320// foo->bar1321// This is actually well-formed in C++ if MyRecord has an1322// overloaded operator->, but that should have been dealt with1323// by now--or a diagnostic message already issued if a problem1324// was encountered while looking for the overloaded operator->.1325if (!S.getLangOpts().CPlusPlus) {1326S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)1327<< BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()1328<< FixItHint::CreateReplacement(OpLoc, ".");1329}1330IsArrow = false;1331} else {1332S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)1333<< BaseType << BaseExpr.get()->getSourceRange();1334return ExprError();1335}1336}13371338// If the base type is an atomic type, this access is undefined behavior per1339// C11 6.5.2.3p5. Instead of giving a typecheck error, we'll warn the user1340// about the UB and recover by converting the atomic lvalue into a non-atomic1341// lvalue. Because this is inherently unsafe as an atomic operation, the1342// warning defaults to an error.1343if (const auto *ATy = BaseType->getAs<AtomicType>()) {1344S.DiagRuntimeBehavior(OpLoc, nullptr,1345S.PDiag(diag::warn_atomic_member_access));1346BaseType = ATy->getValueType().getUnqualifiedType();1347BaseExpr = ImplicitCastExpr::Create(1348S.Context, IsArrow ? S.Context.getPointerType(BaseType) : BaseType,1349CK_AtomicToNonAtomic, BaseExpr.get(), nullptr,1350BaseExpr.get()->getValueKind(), FPOptionsOverride());1351}13521353// Handle field access to simple records.1354if (BaseType->getAsRecordDecl()) {1355TypoExpr *TE = nullptr;1356if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow,1357SS, HasTemplateArgs, TemplateKWLoc, TE))1358return ExprError();13591360// Returning valid-but-null is how we indicate to the caller that1361// the lookup result was filled in. If typo correction was attempted and1362// failed, the lookup result will have been cleared--that combined with the1363// valid-but-null ExprResult will trigger the appropriate diagnostics.1364return ExprResult(TE);1365} else if (BaseType->isDependentType()) {1366R.setNotFoundInCurrentInstantiation();1367return ExprEmpty();1368}13691370// Handle ivar access to Objective-C objects.1371if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) {1372if (!SS.isEmpty() && !SS.isInvalid()) {1373S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)1374<< 1 << SS.getScopeRep()1375<< FixItHint::CreateRemoval(SS.getRange());1376SS.clear();1377}13781379IdentifierInfo *Member = MemberName.getAsIdentifierInfo();13801381// There are three cases for the base type:1382// - builtin id (qualified or unqualified)1383// - builtin Class (qualified or unqualified)1384// - an interface1385ObjCInterfaceDecl *IDecl = OTy->getInterface();1386if (!IDecl) {1387if (S.getLangOpts().ObjCAutoRefCount &&1388(OTy->isObjCId() || OTy->isObjCClass()))1389goto fail;1390// There's an implicit 'isa' ivar on all objects.1391// But we only actually find it this way on objects of type 'id',1392// apparently.1393if (OTy->isObjCId() && Member->isStr("isa"))1394return new (S.Context) ObjCIsaExpr(BaseExpr.get(), IsArrow, MemberLoc,1395OpLoc, S.Context.getObjCClassType());1396if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))1397return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1398ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1399goto fail;1400}14011402if (S.RequireCompleteType(OpLoc, BaseType,1403diag::err_typecheck_incomplete_tag,1404BaseExpr.get()))1405return ExprError();14061407ObjCInterfaceDecl *ClassDeclared = nullptr;1408ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);14091410if (!IV) {1411// Attempt to correct for typos in ivar names.1412DeclFilterCCC<ObjCIvarDecl> Validator{};1413Validator.IsObjCIvarLookup = IsArrow;1414if (TypoCorrection Corrected = S.CorrectTypo(1415R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,1416Validator, Sema::CTK_ErrorRecovery, IDecl)) {1417IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();1418S.diagnoseTypo(1419Corrected,1420S.PDiag(diag::err_typecheck_member_reference_ivar_suggest)1421<< IDecl->getDeclName() << MemberName);14221423// Figure out the class that declares the ivar.1424assert(!ClassDeclared);14251426Decl *D = cast<Decl>(IV->getDeclContext());1427if (auto *Category = dyn_cast<ObjCCategoryDecl>(D))1428D = Category->getClassInterface();14291430if (auto *Implementation = dyn_cast<ObjCImplementationDecl>(D))1431ClassDeclared = Implementation->getClassInterface();1432else if (auto *Interface = dyn_cast<ObjCInterfaceDecl>(D))1433ClassDeclared = Interface;14341435assert(ClassDeclared && "cannot query interface");1436} else {1437if (IsArrow &&1438IDecl->FindPropertyDeclaration(1439Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {1440S.Diag(MemberLoc, diag::err_property_found_suggest)1441<< Member << BaseExpr.get()->getType()1442<< FixItHint::CreateReplacement(OpLoc, ".");1443return ExprError();1444}14451446S.Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)1447<< IDecl->getDeclName() << MemberName1448<< BaseExpr.get()->getSourceRange();1449return ExprError();1450}1451}14521453assert(ClassDeclared);14541455// If the decl being referenced had an error, return an error for this1456// sub-expr without emitting another error, in order to avoid cascading1457// error cases.1458if (IV->isInvalidDecl())1459return ExprError();14601461// Check whether we can reference this field.1462if (S.DiagnoseUseOfDecl(IV, MemberLoc))1463return ExprError();1464if (IV->getAccessControl() != ObjCIvarDecl::Public &&1465IV->getAccessControl() != ObjCIvarDecl::Package) {1466ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;1467if (ObjCMethodDecl *MD = S.getCurMethodDecl())1468ClassOfMethodDecl = MD->getClassInterface();1469else if (ObjCImpDecl && S.getCurFunctionDecl()) {1470// Case of a c-function declared inside an objc implementation.1471// FIXME: For a c-style function nested inside an objc implementation1472// class, there is no implementation context available, so we pass1473// down the context as argument to this routine. Ideally, this context1474// need be passed down in the AST node and somehow calculated from the1475// AST for a function decl.1476if (ObjCImplementationDecl *IMPD =1477dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))1478ClassOfMethodDecl = IMPD->getClassInterface();1479else if (ObjCCategoryImplDecl* CatImplClass =1480dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl))1481ClassOfMethodDecl = CatImplClass->getClassInterface();1482}1483if (!S.getLangOpts().DebuggerSupport) {1484if (IV->getAccessControl() == ObjCIvarDecl::Private) {1485if (!declaresSameEntity(ClassDeclared, IDecl) ||1486!declaresSameEntity(ClassOfMethodDecl, ClassDeclared))1487S.Diag(MemberLoc, diag::err_private_ivar_access)1488<< IV->getDeclName();1489} else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))1490// @protected1491S.Diag(MemberLoc, diag::err_protected_ivar_access)1492<< IV->getDeclName();1493}1494}1495bool warn = true;1496if (S.getLangOpts().ObjCWeak) {1497Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts();1498if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp))1499if (UO->getOpcode() == UO_Deref)1500BaseExp = UO->getSubExpr()->IgnoreParenCasts();15011502if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp))1503if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {1504S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access);1505warn = false;1506}1507}1508if (warn) {1509if (ObjCMethodDecl *MD = S.getCurMethodDecl()) {1510ObjCMethodFamily MF = MD->getMethodFamily();1511warn = (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&1512!S.ObjC().IvarBacksCurrentMethodAccessor(IDecl, MD, IV));1513}1514if (warn)1515S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();1516}15171518ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr(1519IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(),1520IsArrow);15211522if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {1523if (!S.isUnevaluatedContext() &&1524!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))1525S.getCurFunction()->recordUseOfWeak(Result);1526}15271528return Result;1529}15301531// Objective-C property access.1532const ObjCObjectPointerType *OPT;1533if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {1534if (!SS.isEmpty() && !SS.isInvalid()) {1535S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)1536<< 0 << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());1537SS.clear();1538}15391540// This actually uses the base as an r-value.1541BaseExpr = S.DefaultLvalueConversion(BaseExpr.get());1542if (BaseExpr.isInvalid())1543return ExprError();15441545assert(S.Context.hasSameUnqualifiedType(BaseType,1546BaseExpr.get()->getType()));15471548IdentifierInfo *Member = MemberName.getAsIdentifierInfo();15491550const ObjCObjectType *OT = OPT->getObjectType();15511552// id, with and without qualifiers.1553if (OT->isObjCId()) {1554// Check protocols on qualified interfaces.1555Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);1556if (Decl *PMDecl =1557FindGetterSetterNameDecl(OPT, Member, Sel, S.Context)) {1558if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {1559// Check the use of this declaration1560if (S.DiagnoseUseOfDecl(PD, MemberLoc))1561return ExprError();15621563return new (S.Context)1564ObjCPropertyRefExpr(PD, S.Context.PseudoObjectTy, VK_LValue,1565OK_ObjCProperty, MemberLoc, BaseExpr.get());1566}15671568if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {1569Selector SetterSel =1570SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),1571S.PP.getSelectorTable(),1572Member);1573ObjCMethodDecl *SMD = nullptr;1574if (Decl *SDecl = FindGetterSetterNameDecl(OPT,1575/*Property id*/ nullptr,1576SetterSel, S.Context))1577SMD = dyn_cast<ObjCMethodDecl>(SDecl);15781579return new (S.Context)1580ObjCPropertyRefExpr(OMD, SMD, S.Context.PseudoObjectTy, VK_LValue,1581OK_ObjCProperty, MemberLoc, BaseExpr.get());1582}1583}1584// Use of id.member can only be for a property reference. Do not1585// use the 'id' redefinition in this case.1586if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr))1587return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1588ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);15891590return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)1591<< MemberName << BaseType);1592}15931594// 'Class', unqualified only.1595if (OT->isObjCClass()) {1596// Only works in a method declaration (??!).1597ObjCMethodDecl *MD = S.getCurMethodDecl();1598if (!MD) {1599if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))1600return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1601ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);16021603goto fail;1604}16051606// Also must look for a getter name which uses property syntax.1607Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member);1608ObjCInterfaceDecl *IFace = MD->getClassInterface();1609if (!IFace)1610goto fail;16111612ObjCMethodDecl *Getter;1613if ((Getter = IFace->lookupClassMethod(Sel))) {1614// Check the use of this method.1615if (S.DiagnoseUseOfDecl(Getter, MemberLoc))1616return ExprError();1617} else1618Getter = IFace->lookupPrivateMethod(Sel, false);1619// If we found a getter then this may be a valid dot-reference, we1620// will look for the matching setter, in case it is needed.1621Selector SetterSel =1622SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),1623S.PP.getSelectorTable(),1624Member);1625ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);1626if (!Setter) {1627// If this reference is in an @implementation, also check for 'private'1628// methods.1629Setter = IFace->lookupPrivateMethod(SetterSel, false);1630}16311632if (Setter && S.DiagnoseUseOfDecl(Setter, MemberLoc))1633return ExprError();16341635if (Getter || Setter) {1636return new (S.Context) ObjCPropertyRefExpr(1637Getter, Setter, S.Context.PseudoObjectTy, VK_LValue,1638OK_ObjCProperty, MemberLoc, BaseExpr.get());1639}16401641if (ShouldTryAgainWithRedefinitionType(S, BaseExpr))1642return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1643ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);16441645return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)1646<< MemberName << BaseType);1647}16481649// Normal property access.1650return S.ObjC().HandleExprPropertyRefExpr(1651OPT, BaseExpr.get(), OpLoc, MemberName, MemberLoc, SourceLocation(),1652QualType(), false);1653}16541655if (BaseType->isExtVectorBoolType()) {1656// We disallow element access for ext_vector_type bool. There is no way to1657// materialize a reference to a vector element as a pointer (each element is1658// one bit in the vector).1659S.Diag(R.getNameLoc(), diag::err_ext_vector_component_name_illegal)1660<< MemberName1661<< (BaseExpr.get() ? BaseExpr.get()->getSourceRange() : SourceRange());1662return ExprError();1663}16641665// Handle 'field access' to vectors, such as 'V.xx'.1666if (BaseType->isExtVectorType()) {1667// FIXME: this expr should store IsArrow.1668IdentifierInfo *Member = MemberName.getAsIdentifierInfo();1669ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());1670QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc,1671Member, MemberLoc);1672if (ret.isNull())1673return ExprError();1674Qualifiers BaseQ =1675S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers();1676ret = S.Context.getQualifiedType(ret, BaseQ);16771678return new (S.Context)1679ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc);1680}16811682// Adjust builtin-sel to the appropriate redefinition type if that's1683// not just a pointer to builtin-sel again.1684if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) &&1685!S.Context.getObjCSelRedefinitionType()->isObjCSelType()) {1686BaseExpr = S.ImpCastExprToType(1687BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast);1688return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1689ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1690}16911692// Failure cases.1693fail:16941695// Recover from dot accesses to pointers, e.g.:1696// type *foo;1697// foo.bar1698// This is actually well-formed in two cases:1699// - 'type' is an Objective C type1700// - 'bar' is a pseudo-destructor name which happens to refer to1701// the appropriate pointer type1702if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {1703if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&1704MemberName.getNameKind() != DeclarationName::CXXDestructorName) {1705S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)1706<< BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()1707<< FixItHint::CreateReplacement(OpLoc, "->");17081709if (S.isSFINAEContext())1710return ExprError();17111712// Recurse as an -> access.1713IsArrow = true;1714return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1715ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1716}1717}17181719// If the user is trying to apply -> or . to a function name, it's probably1720// because they forgot parentheses to call that function.1721if (S.tryToRecoverWithCall(1722BaseExpr, S.PDiag(diag::err_member_reference_needs_call),1723/*complain*/ false,1724IsArrow ? &isPointerToRecordType : &isRecordType)) {1725if (BaseExpr.isInvalid())1726return ExprError();1727BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get());1728return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,1729ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);1730}17311732// HLSL supports implicit conversion of scalar types to single element vector1733// rvalues in member expressions.1734if (S.getLangOpts().HLSL && BaseType->isScalarType()) {1735QualType VectorTy = S.Context.getExtVectorType(BaseType, 1);1736BaseExpr = S.ImpCastExprToType(BaseExpr.get(), VectorTy, CK_VectorSplat,1737BaseExpr.get()->getValueKind());1738return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl,1739HasTemplateArgs, TemplateKWLoc);1740}17411742S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)1743<< BaseType << BaseExpr.get()->getSourceRange() << MemberLoc;17441745return ExprError();1746}17471748ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,1749SourceLocation OpLoc,1750tok::TokenKind OpKind, CXXScopeSpec &SS,1751SourceLocation TemplateKWLoc,1752UnqualifiedId &Id, Decl *ObjCImpDecl) {1753// Warn about the explicit constructor calls Microsoft extension.1754if (getLangOpts().MicrosoftExt &&1755Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)1756Diag(Id.getSourceRange().getBegin(),1757diag::ext_ms_explicit_constructor_call);17581759TemplateArgumentListInfo TemplateArgsBuffer;17601761// Decompose the name into its component parts.1762DeclarationNameInfo NameInfo;1763const TemplateArgumentListInfo *TemplateArgs;1764DecomposeUnqualifiedId(Id, TemplateArgsBuffer,1765NameInfo, TemplateArgs);17661767bool IsArrow = (OpKind == tok::arrow);17681769if (getLangOpts().HLSL && IsArrow)1770return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2);17711772NamedDecl *FirstQualifierInScope1773= (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep()));17741775// This is a postfix expression, so get rid of ParenListExprs.1776ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);1777if (Result.isInvalid()) return ExprError();1778Base = Result.get();17791780ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};1781ExprResult Res = BuildMemberReferenceExpr(1782Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc,1783FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs);17841785if (!Res.isInvalid() && isa<MemberExpr>(Res.get()))1786CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get()));17871788return Res;1789}17901791void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {1792if (isUnevaluatedContext())1793return;17941795QualType ResultTy = E->getType();17961797// Member accesses have four cases:1798// 1: non-array member via "->": dereferences1799// 2: non-array member via ".": nothing interesting happens1800// 3: array member access via "->": nothing interesting happens1801// (this returns an array lvalue and does not actually dereference memory)1802// 4: array member access via ".": *adds* a layer of indirection1803if (ResultTy->isArrayType()) {1804if (!E->isArrow()) {1805// This might be something like:1806// (*structPtr).arrayMember1807// which behaves roughly like:1808// &(*structPtr).pointerMember1809// in that the apparent dereference in the base expression does not1810// actually happen.1811CheckAddressOfNoDeref(E->getBase());1812}1813} else if (E->isArrow()) {1814if (const auto *Ptr = dyn_cast<PointerType>(1815E->getBase()->getType().getDesugaredType(Context))) {1816if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))1817ExprEvalContexts.back().PossibleDerefs.insert(E);1818}1819}1820}18211822ExprResult1823Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,1824SourceLocation OpLoc, const CXXScopeSpec &SS,1825FieldDecl *Field, DeclAccessPair FoundDecl,1826const DeclarationNameInfo &MemberNameInfo) {1827// x.a is an l-value if 'a' has a reference type. Otherwise:1828// x.a is an l-value/x-value/pr-value if the base is (and note1829// that *x is always an l-value), except that if the base isn't1830// an ordinary object then we must have an rvalue.1831ExprValueKind VK = VK_LValue;1832ExprObjectKind OK = OK_Ordinary;1833if (!IsArrow) {1834if (BaseExpr->getObjectKind() == OK_Ordinary)1835VK = BaseExpr->getValueKind();1836else1837VK = VK_PRValue;1838}1839if (VK != VK_PRValue && Field->isBitField())1840OK = OK_BitField;18411842// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]1843QualType MemberType = Field->getType();1844if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {1845MemberType = Ref->getPointeeType();1846VK = VK_LValue;1847} else {1848QualType BaseType = BaseExpr->getType();1849if (IsArrow) BaseType = BaseType->castAs<PointerType>()->getPointeeType();18501851Qualifiers BaseQuals = BaseType.getQualifiers();18521853// GC attributes are never picked up by members.1854BaseQuals.removeObjCGCAttr();18551856// CVR attributes from the base are picked up by members,1857// except that 'mutable' members don't pick up 'const'.1858if (Field->isMutable()) BaseQuals.removeConst();18591860Qualifiers MemberQuals =1861Context.getCanonicalType(MemberType).getQualifiers();18621863assert(!MemberQuals.hasAddressSpace());18641865Qualifiers Combined = BaseQuals + MemberQuals;1866if (Combined != MemberQuals)1867MemberType = Context.getQualifiedType(MemberType, Combined);18681869// Pick up NoDeref from the base in case we end up using AddrOf on the1870// result. E.g. the expression1871// &someNoDerefPtr->pointerMember1872// should be a noderef pointer again.1873if (BaseType->hasAttr(attr::NoDeref))1874MemberType =1875Context.getAttributedType(attr::NoDeref, MemberType, MemberType);1876}18771878auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);1879if (!(CurMethod && CurMethod->isDefaulted()))1880UnusedPrivateFields.remove(Field);18811882ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),1883FoundDecl, Field);1884if (Base.isInvalid())1885return ExprError();18861887// Build a reference to a private copy for non-static data members in1888// non-static member functions, privatized by OpenMP constructs.1889if (getLangOpts().OpenMP && IsArrow &&1890!CurContext->isDependentContext() &&1891isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {1892if (auto *PrivateCopy = OpenMP().isOpenMPCapturedDecl(Field)) {1893return OpenMP().getOpenMPCapturedExpr(PrivateCopy, VK, OK,1894MemberNameInfo.getLoc());1895}1896}18971898return BuildMemberExpr(1899Base.get(), IsArrow, OpLoc, SS.getWithLocInContext(Context),1900/*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,1901/*HadMultipleCandidates=*/false, MemberNameInfo, MemberType, VK, OK);1902}19031904ExprResult1905Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,1906SourceLocation TemplateKWLoc,1907LookupResult &R,1908const TemplateArgumentListInfo *TemplateArgs,1909bool IsKnownInstance, const Scope *S) {1910assert(!R.empty() && !R.isAmbiguous());19111912SourceLocation loc = R.getNameLoc();19131914// If this is known to be an instance access, go ahead and build an1915// implicit 'this' expression now.1916QualType ThisTy = getCurrentThisType();1917assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");19181919Expr *baseExpr = nullptr; // null signifies implicit access1920if (IsKnownInstance) {1921SourceLocation Loc = R.getNameLoc();1922if (SS.getRange().isValid())1923Loc = SS.getRange().getBegin();1924baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true);1925}19261927return BuildMemberReferenceExpr(1928baseExpr, ThisTy,1929/*OpLoc=*/SourceLocation(),1930/*IsArrow=*/!getLangOpts().HLSL, SS, TemplateKWLoc,1931/*FirstQualifierInScope=*/nullptr, R, TemplateArgs, S);1932}193319341935