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