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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis member access expressions.
10//
11//===----------------------------------------------------------------------===//
12#include "clang/AST/ASTLambda.h"
13#include "clang/AST/DeclCXX.h"
14#include "clang/AST/DeclObjC.h"
15#include "clang/AST/DeclTemplate.h"
16#include "clang/AST/ExprCXX.h"
17#include "clang/AST/ExprObjC.h"
18#include "clang/Lex/Preprocessor.h"
19#include "clang/Sema/Lookup.h"
20#include "clang/Sema/Overload.h"
21#include "clang/Sema/Scope.h"
22#include "clang/Sema/ScopeInfo.h"
23#include "clang/Sema/SemaInternal.h"
24#include "clang/Sema/SemaOpenMP.h"
25
26using namespace clang;
27using namespace sema;
28
29typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet;
30
31/// Determines if the given class is provably not derived from all of
32/// the prospective base classes.
33static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record,
34 const BaseSet &Bases) {
35 auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) {
36 return !Bases.count(Ptr: Base->getCanonicalDecl());
37 };
38 return BaseIsNotInSet(Record) && Record->forallBases(BaseMatches: BaseIsNotInSet);
39}
40
41enum IMAKind {
42 /// The reference is definitely not an instance member access.
43 IMA_Static,
44
45 /// The reference may be an implicit instance member access.
46 IMA_Mixed,
47
48 /// The reference may be to an instance member, but it might be invalid if
49 /// so, because the context is not an instance method.
50 IMA_Mixed_StaticOrExplicitContext,
51
52 /// The reference may be to an instance member, but it is invalid if
53 /// so, because the context is from an unrelated class.
54 IMA_Mixed_Unrelated,
55
56 /// The reference is definitely an implicit instance member access.
57 IMA_Instance,
58
59 /// The reference may be to an unresolved using declaration.
60 IMA_Unresolved,
61
62 /// The reference is a contextually-permitted abstract member reference.
63 IMA_Abstract,
64
65 /// Whether the context is static is dependent on the enclosing template (i.e.
66 /// in a dependent class scope explicit specialization).
67 IMA_Dependent,
68
69 /// The reference may be to an unresolved using declaration and the
70 /// context is not an instance method.
71 IMA_Unresolved_StaticOrExplicitContext,
72
73 // The reference refers to a field which is not a member of the containing
74 // class, which is allowed because we're in C++11 mode and the context is
75 // unevaluated.
76 IMA_Field_Uneval_Context,
77
78 /// All possible referrents are instance members and the current
79 /// context is not an instance method.
80 IMA_Error_StaticOrExplicitContext,
81
82 /// All possible referrents are instance members of an unrelated
83 /// class.
84 IMA_Error_Unrelated
85};
86
87/// The given lookup names class member(s) and is not being used for
88/// an address-of-member expression. Classify the type of access
89/// according to whether it's possible that this reference names an
90/// instance member. This is best-effort in dependent contexts; it is okay to
91/// conservatively answer "yes", in which case some errors will simply
92/// not be caught until template-instantiation.
93static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
94 const LookupResult &R) {
95 assert(!R.empty() && (*R.begin())->isCXXClassMember());
96
97 DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
98
99 bool couldInstantiateToStatic = false;
100 bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull();
101
102 if (auto *MD = dyn_cast<CXXMethodDecl>(Val: DC)) {
103 if (MD->isImplicitObjectMemberFunction()) {
104 isStaticOrExplicitContext = false;
105 // A dependent class scope function template explicit specialization
106 // that is neither declared 'static' nor with an explicit object
107 // parameter could instantiate to a static or non-static member function.
108 couldInstantiateToStatic = MD->getDependentSpecializationInfo();
109 }
110 }
111
112 if (R.isUnresolvableResult()) {
113 if (couldInstantiateToStatic)
114 return IMA_Dependent;
115 return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext
116 : IMA_Unresolved;
117 }
118
119 // Collect all the declaring classes of instance members we find.
120 bool hasNonInstance = false;
121 bool isField = false;
122 BaseSet Classes;
123 for (NamedDecl *D : R) {
124 // Look through any using decls.
125 D = D->getUnderlyingDecl();
126
127 if (D->isCXXInstanceMember()) {
128 isField |= isa<FieldDecl>(Val: D) || isa<MSPropertyDecl>(Val: D) ||
129 isa<IndirectFieldDecl>(Val: D);
130
131 CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext());
132 Classes.insert(Ptr: R->getCanonicalDecl());
133 } else
134 hasNonInstance = true;
135 }
136
137 // If we didn't find any instance members, it can't be an implicit
138 // member reference.
139 if (Classes.empty())
140 return IMA_Static;
141
142 if (couldInstantiateToStatic)
143 return IMA_Dependent;
144
145 // C++11 [expr.prim.general]p12:
146 // An id-expression that denotes a non-static data member or non-static
147 // member function of a class can only be used:
148 // (...)
149 // - if that id-expression denotes a non-static data member and it
150 // appears in an unevaluated operand.
151 //
152 // This rule is specific to C++11. However, we also permit this form
153 // in unevaluated inline assembly operands, like the operand to a SIZE.
154 IMAKind AbstractInstanceResult = IMA_Static; // happens to be 'false'
155 assert(!AbstractInstanceResult);
156 switch (SemaRef.ExprEvalContexts.back().Context) {
157 case Sema::ExpressionEvaluationContext::Unevaluated:
158 case Sema::ExpressionEvaluationContext::UnevaluatedList:
159 if (isField && SemaRef.getLangOpts().CPlusPlus11)
160 AbstractInstanceResult = IMA_Field_Uneval_Context;
161 break;
162
163 case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
164 AbstractInstanceResult = IMA_Abstract;
165 break;
166
167 case Sema::ExpressionEvaluationContext::DiscardedStatement:
168 case Sema::ExpressionEvaluationContext::ConstantEvaluated:
169 case Sema::ExpressionEvaluationContext::ImmediateFunctionContext:
170 case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
171 case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
172 break;
173 }
174
175 // If the current context is not an instance method, it can't be
176 // an implicit member reference.
177 if (isStaticOrExplicitContext) {
178 if (hasNonInstance)
179 return IMA_Mixed_StaticOrExplicitContext;
180
181 return AbstractInstanceResult ? AbstractInstanceResult
182 : IMA_Error_StaticOrExplicitContext;
183 }
184
185 CXXRecordDecl *contextClass;
186 if (auto *MD = dyn_cast<CXXMethodDecl>(Val: DC))
187 contextClass = MD->getParent()->getCanonicalDecl();
188 else if (auto *RD = dyn_cast<CXXRecordDecl>(Val: DC))
189 contextClass = RD;
190 else
191 return AbstractInstanceResult ? AbstractInstanceResult
192 : IMA_Error_StaticOrExplicitContext;
193
194 // [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 a
197 // 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 expression
199 // is ill-formed.
200 if (R.getNamingClass() &&
201 contextClass->getCanonicalDecl() !=
202 R.getNamingClass()->getCanonicalDecl()) {
203 // If the naming class is not the current context, this was a qualified
204 // member name lookup, and it's sufficient to check that we have the naming
205 // class as a base class.
206 Classes.clear();
207 Classes.insert(Ptr: R.getNamingClass()->getCanonicalDecl());
208 }
209
210 // If we can prove that the current context is unrelated to all the
211 // declaring classes, it can't be an implicit member reference (in
212 // which case it's an error if any of those members are selected).
213 if (isProvablyNotDerivedFrom(SemaRef, Record: contextClass, Bases: Classes))
214 return hasNonInstance ? IMA_Mixed_Unrelated :
215 AbstractInstanceResult ? AbstractInstanceResult :
216 IMA_Error_Unrelated;
217
218 return (hasNonInstance ? IMA_Mixed : IMA_Instance);
219}
220
221/// Diagnose a reference to a field with no object available.
222static void diagnoseInstanceReference(Sema &SemaRef,
223 const CXXScopeSpec &SS,
224 NamedDecl *Rep,
225 const DeclarationNameInfo &nameInfo) {
226 SourceLocation Loc = nameInfo.getLoc();
227 SourceRange Range(Loc);
228 if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
229
230 // Look through using shadow decls and aliases.
231 Rep = Rep->getUnderlyingDecl();
232
233 DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
234 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Val: FunctionLevelDC);
235 CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;
236 CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());
237
238 bool InStaticMethod = Method && Method->isStatic();
239 bool InExplicitObjectMethod =
240 Method && Method->isExplicitObjectMemberFunction();
241 bool IsField = isa<FieldDecl>(Val: Rep) || isa<IndirectFieldDecl>(Val: Rep);
242
243 std::string Replacement;
244 if (InExplicitObjectMethod) {
245 DeclarationName N = Method->getParamDecl(0)->getDeclName();
246 if (!N.isEmpty()) {
247 Replacement.append(str: N.getAsString());
248 Replacement.append(s: ".");
249 }
250 }
251 if (IsField && InStaticMethod)
252 // "invalid use of member 'x' in static member function"
253 SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)
254 << Range << nameInfo.getName() << /*static*/ 0;
255 else if (IsField && InExplicitObjectMethod) {
256 auto Diag = SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)
257 << Range << nameInfo.getName() << /*explicit*/ 1;
258 if (!Replacement.empty())
259 Diag << FixItHint::CreateInsertion(InsertionLoc: Loc, Code: Replacement);
260 } else if (ContextClass && RepClass && SS.isEmpty() &&
261 !InExplicitObjectMethod && !InStaticMethod &&
262 !RepClass->Equals(ContextClass) &&
263 RepClass->Encloses(ContextClass))
264 // Unqualified lookup in a non-static member function found a member of an
265 // enclosing class.
266 SemaRef.Diag(Loc, diag::err_nested_non_static_member_use)
267 << IsField << RepClass << nameInfo.getName() << ContextClass << Range;
268 else if (IsField)
269 SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
270 << nameInfo.getName() << Range;
271 else if (!InExplicitObjectMethod)
272 SemaRef.Diag(Loc, diag::err_member_call_without_object)
273 << Range << /*static*/ 0;
274 else {
275 if (const auto *Tpl = dyn_cast<FunctionTemplateDecl>(Val: Rep))
276 Rep = Tpl->getTemplatedDecl();
277 const auto *Callee = cast<CXXMethodDecl>(Val: Rep);
278 auto Diag = SemaRef.Diag(Loc, diag::err_member_call_without_object)
279 << Range << Callee->isExplicitObjectMemberFunction();
280 if (!Replacement.empty())
281 Diag << FixItHint::CreateInsertion(InsertionLoc: Loc, Code: Replacement);
282 }
283}
284
285bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS,
286 LookupResult &R,
287 bool IsAddressOfOperand) {
288 if (!getLangOpts().CPlusPlus)
289 return false;
290 else if (R.empty() || !R.begin()->isCXXClassMember())
291 return false;
292 else if (!IsAddressOfOperand)
293 return true;
294 else if (!SS.isEmpty())
295 return false;
296 else if (R.isOverloadedResult())
297 return false;
298 else if (R.isUnresolvableResult())
299 return true;
300 else
301 return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(Val: R.getFoundDecl());
302}
303
304/// Builds an expression which might be an implicit member expression.
305ExprResult Sema::BuildPossibleImplicitMemberExpr(
306 const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
307 const TemplateArgumentListInfo *TemplateArgs, const Scope *S) {
308 switch (IMAKind Classification = ClassifyImplicitMemberAccess(SemaRef&: *this, R)) {
309 case IMA_Instance:
310 case IMA_Mixed:
311 case IMA_Mixed_Unrelated:
312 case IMA_Unresolved:
313 return BuildImplicitMemberExpr(
314 SS, TemplateKWLoc, R, TemplateArgs,
315 /*IsKnownInstance=*/IsDefiniteInstance: Classification == IMA_Instance, S);
316 case IMA_Field_Uneval_Context:
317 Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
318 << R.getLookupNameInfo().getName();
319 [[fallthrough]];
320 case IMA_Static:
321 case IMA_Abstract:
322 case IMA_Mixed_StaticOrExplicitContext:
323 case IMA_Unresolved_StaticOrExplicitContext:
324 if (TemplateArgs || TemplateKWLoc.isValid())
325 return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,
326 TemplateArgs);
327 return BuildDeclarationNameExpr(SS, R, /*NeedsADL=*/false,
328 /*AcceptInvalidDecl=*/false);
329 case IMA_Dependent:
330 R.suppressDiagnostics();
331 return UnresolvedLookupExpr::Create(
332 Context, NamingClass: R.getNamingClass(), QualifierLoc: SS.getWithLocInContext(Context),
333 TemplateKWLoc, NameInfo: R.getLookupNameInfo(), /*RequiresADL=*/false,
334 Args: TemplateArgs, Begin: R.begin(), End: R.end(), /*KnownDependent=*/true);
335
336 case IMA_Error_StaticOrExplicitContext:
337 case IMA_Error_Unrelated:
338 diagnoseInstanceReference(SemaRef&: *this, SS, Rep: R.getRepresentativeDecl(),
339 nameInfo: R.getLookupNameInfo());
340 return ExprError();
341 }
342
343 llvm_unreachable("unexpected instance member access kind");
344}
345
346/// Determine whether input char is from rgba component set.
347static bool
348IsRGBA(char c) {
349 switch (c) {
350 case 'r':
351 case 'g':
352 case 'b':
353 case 'a':
354 return true;
355 default:
356 return false;
357 }
358}
359
360// OpenCL v1.1, s6.1.7
361// The component swizzle length must be in accordance with the acceptable
362// vector sizes.
363static bool IsValidOpenCLComponentSwizzleLength(unsigned len)
364{
365 return (len >= 1 && len <= 4) || len == 8 || len == 16;
366}
367
368/// Check an ext-vector component access expression.
369///
370/// VK should be set in advance to the value kind of the base
371/// expression.
372static QualType
373CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
374 SourceLocation OpLoc, const IdentifierInfo *CompName,
375 SourceLocation CompLoc) {
376 // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,
377 // see FIXME there.
378 //
379 // FIXME: This logic can be greatly simplified by splitting it along
380 // halving/not halving and reworking the component checking.
381 const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();
382
383 // The vector accessor can't exceed the number of elements.
384 const char *compStr = CompName->getNameStart();
385
386 // This flag determines whether or not the component is one of the four
387 // special names that indicate a subset of exactly half the elements are
388 // to be selected.
389 bool HalvingSwizzle = false;
390
391 // 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.
393 bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1];
394
395 bool HasRepeated = false;
396 bool HasIndex[16] = {};
397
398 int Idx;
399
400 // Check that we've found one of the special components, or that the component
401 // names must come from the same set.
402 if (!strcmp(s1: compStr, s2: "hi") || !strcmp(s1: compStr, s2: "lo") ||
403 !strcmp(s1: compStr, s2: "even") || !strcmp(s1: compStr, s2: "odd")) {
404 HalvingSwizzle = true;
405 } else if (!HexSwizzle &&
406 (Idx = vecType->getPointAccessorIdx(c: *compStr)) != -1) {
407 bool HasRGBA = IsRGBA(c: *compStr);
408 do {
409 // Ensure that xyzw and rgba components don't intermingle.
410 if (HasRGBA != IsRGBA(c: *compStr))
411 break;
412 if (HasIndex[Idx]) HasRepeated = true;
413 HasIndex[Idx] = true;
414 compStr++;
415 } while (*compStr && (Idx = vecType->getPointAccessorIdx(c: *compStr)) != -1);
416
417 // Emit a warning if an rgba selector is used earlier than OpenCL C 3.0.
418 if (HasRGBA || (*compStr && IsRGBA(c: *compStr))) {
419 if (S.getLangOpts().OpenCL &&
420 S.getLangOpts().getOpenCLCompatibleVersion() < 300) {
421 const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr;
422 S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector)
423 << StringRef(DiagBegin, 1) << SourceRange(CompLoc);
424 }
425 }
426 } else {
427 if (HexSwizzle) compStr++;
428 while ((Idx = vecType->getNumericAccessorIdx(c: *compStr)) != -1) {
429 if (HasIndex[Idx]) HasRepeated = true;
430 HasIndex[Idx] = true;
431 compStr++;
432 }
433 }
434
435 if (!HalvingSwizzle && *compStr) {
436 // We didn't get to the end of the string. This means the component names
437 // didn't come from the same set *or* we encountered an illegal name.
438 S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
439 << StringRef(compStr, 1) << SourceRange(CompLoc);
440 return QualType();
441 }
442
443 // Ensure no component accessor exceeds the width of the vector type it
444 // operates on.
445 if (!HalvingSwizzle) {
446 compStr = CompName->getNameStart();
447
448 if (HexSwizzle)
449 compStr++;
450
451 while (*compStr) {
452 if (!vecType->isAccessorWithinNumElements(c: *compStr++, isNumericAccessor: HexSwizzle)) {
453 S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
454 << baseType << SourceRange(CompLoc);
455 return QualType();
456 }
457 }
458 }
459
460 // OpenCL mode requires swizzle length to be in accordance with accepted
461 // sizes. Clang however supports arbitrary lengths for other languages.
462 if (S.getLangOpts().OpenCL && !HalvingSwizzle) {
463 unsigned SwizzleLength = CompName->getLength();
464
465 if (HexSwizzle)
466 SwizzleLength--;
467
468 if (IsValidOpenCLComponentSwizzleLength(len: SwizzleLength) == false) {
469 S.Diag(OpLoc, diag::err_opencl_ext_vector_component_invalid_length)
470 << SwizzleLength << SourceRange(CompLoc);
471 return QualType();
472 }
473 }
474
475 // 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.
480 unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2
481 : CompName->getLength();
482 if (HexSwizzle)
483 CompSize--;
484
485 if (CompSize == 1)
486 return vecType->getElementType();
487
488 if (HasRepeated)
489 VK = VK_PRValue;
490
491 QualType VT = S.Context.getExtVectorType(VectorType: vecType->getElementType(), NumElts: 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.
494 for (Sema::ExtVectorDeclsType::iterator
495 I = S.ExtVectorDecls.begin(source: S.getExternalSource()),
496 E = S.ExtVectorDecls.end();
497 I != E; ++I) {
498 if ((*I)->getUnderlyingType() == VT)
499 return S.Context.getTypedefType(Decl: *I);
500 }
501
502 return VT; // should never get here (a typedef type should always be found).
503}
504
505static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl,
506 IdentifierInfo *Member,
507 const Selector &Sel,
508 ASTContext &Context) {
509 if (Member)
510 if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(
511 Member, ObjCPropertyQueryKind::OBJC_PR_query_instance))
512 return PD;
513 if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel))
514 return OMD;
515
516 for (const auto *I : PDecl->protocols()) {
517 if (Decl *D = FindGetterSetterNameDeclFromProtocolList(PDecl: I, Member, Sel,
518 Context))
519 return D;
520 }
521 return nullptr;
522}
523
524static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
525 IdentifierInfo *Member,
526 const Selector &Sel,
527 ASTContext &Context) {
528 // Check protocols on qualified interfaces.
529 Decl *GDecl = nullptr;
530 for (const auto *I : QIdTy->quals()) {
531 if (Member)
532 if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration(
533 Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
534 GDecl = PD;
535 break;
536 }
537 // Also must look for a getter or setter name which uses property syntax.
538 if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) {
539 GDecl = OMD;
540 break;
541 }
542 }
543 if (!GDecl) {
544 for (const auto *I : QIdTy->quals()) {
545 // Search in the protocol-qualifier list of current protocol.
546 GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context);
547 if (GDecl)
548 return GDecl;
549 }
550 }
551 return GDecl;
552}
553
554ExprResult
555Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
556 bool IsArrow, SourceLocation OpLoc,
557 const CXXScopeSpec &SS,
558 SourceLocation TemplateKWLoc,
559 NamedDecl *FirstQualifierInScope,
560 const DeclarationNameInfo &NameInfo,
561 const TemplateArgumentListInfo *TemplateArgs) {
562 // Even in dependent contexts, try to diagnose base expressions with
563 // 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 be
569 // accessing the 'f' property if T is an Obj-C interface. The extra check
570 // allows this, while still reporting an error if T is a struct pointer.
571 if (!IsArrow) {
572 const PointerType *PT = BaseType->getAs<PointerType>();
573 if (PT && (!getLangOpts().ObjC ||
574 PT->getPointeeType()->isRecordType())) {
575 assert(BaseExpr && "cannot happen with implicit member accesses");
576 Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
577 << BaseType << BaseExpr->getSourceRange() << NameInfo.getSourceRange();
578 return ExprError();
579 }
580 }
581
582 assert(BaseType->isDependentType() || NameInfo.getName().isDependentName() ||
583 isDependentScopeSpecifier(SS) ||
584 (TemplateArgs && llvm::any_of(TemplateArgs->arguments(),
585 [](const TemplateArgumentLoc &Arg) {
586 return Arg.getArgument().isDependent();
587 })));
588
589 // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
590 // must have pointer type, and the accessed type is the pointee.
591 return CXXDependentScopeMemberExpr::Create(
592 Ctx: Context, Base: BaseExpr, BaseType, IsArrow, OperatorLoc: OpLoc,
593 QualifierLoc: SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierFoundInScope: FirstQualifierInScope,
594 MemberNameInfo: NameInfo, TemplateArgs);
595}
596
597/// We know that the given qualified member reference points only to
598/// declarations which do not belong to the static type of the base
599/// expression. Diagnose the problem.
600static void DiagnoseQualifiedMemberReference(Sema &SemaRef,
601 Expr *BaseExpr,
602 QualType BaseType,
603 const CXXScopeSpec &SS,
604 NamedDecl *rep,
605 const DeclarationNameInfo &nameInfo) {
606 // If this is an implicit member access, use a different set of
607 // diagnostics.
608 if (!BaseExpr)
609 return diagnoseInstanceReference(SemaRef, SS, Rep: rep, nameInfo);
610
611 SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated)
612 << SS.getRange() << rep << BaseType;
613}
614
615// Check whether the declarations we found through a nested-name
616// specifier in a member expression are actually members of the base
617// type. The restriction here is:
618//
619// C++ [expr.ref]p2:
620// ... In these cases, the id-expression shall name a
621// member of the class or of one of its base classes.
622//
623// So it's perfectly legitimate for the nested-name specifier to name
624// an unrelated class, and for us to find an overload set including
625// decls from classes which are not superclasses, as long as the decl
626// we actually pick through overload resolution is from a superclass.
627bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
628 QualType BaseType,
629 const CXXScopeSpec &SS,
630 const LookupResult &R) {
631 CXXRecordDecl *BaseRecord =
632 cast_or_null<CXXRecordDecl>(Val: computeDeclContext(T: BaseType));
633 if (!BaseRecord) {
634 // We can't check this yet because the base type is still
635 // dependent.
636 assert(BaseType->isDependentType());
637 return false;
638 }
639
640 for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
641 // If this is an implicit member reference and we find a
642 // non-instance member, it's not an error.
643 if (!BaseExpr && !(*I)->isCXXInstanceMember())
644 return false;
645
646 // Note that we use the DC of the decl, not the underlying decl.
647 DeclContext *DC = (*I)->getDeclContext()->getNonTransparentContext();
648 if (!DC->isRecord())
649 continue;
650
651 CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(Val: DC)->getCanonicalDecl();
652 if (BaseRecord->getCanonicalDecl() == MemberRecord ||
653 !BaseRecord->isProvablyNotDerivedFrom(Base: MemberRecord))
654 return false;
655 }
656
657 DiagnoseQualifiedMemberReference(SemaRef&: *this, BaseExpr, BaseType, SS,
658 rep: R.getRepresentativeDecl(),
659 nameInfo: R.getLookupNameInfo());
660 return true;
661}
662
663namespace {
664
665// Callback to only accept typo corrections that are either a ValueDecl or a
666// FunctionTemplateDecl and are declared in the current record or, for a C++
667// classes, one of its base classes.
668class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
669public:
670 explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
671 : Record(RTy->getDecl()) {
672 // Don't add bare keywords to the consumer since they will always fail
673 // validation by virtue of not being associated with any decls.
674 WantTypeSpecifiers = false;
675 WantExpressionKeywords = false;
676 WantCXXNamedCasts = false;
677 WantFunctionLikeCasts = false;
678 WantRemainingKeywords = false;
679 }
680
681 bool ValidateCandidate(const TypoCorrection &candidate) override {
682 NamedDecl *ND = candidate.getCorrectionDecl();
683 // Don't accept candidates that cannot be member functions, constants,
684 // variables, or templates.
685 if (!ND || !(isa<ValueDecl>(Val: ND) || isa<FunctionTemplateDecl>(Val: ND)))
686 return false;
687
688 // Accept candidates that occur in the current record.
689 if (Record->containsDecl(ND))
690 return true;
691
692 if (const auto *RD = dyn_cast<CXXRecordDecl>(Val: Record)) {
693 // Accept candidates that occur in any of the current class' base classes.
694 for (const auto &BS : RD->bases()) {
695 if (const auto *BSTy = BS.getType()->getAs<RecordType>()) {
696 if (BSTy->getDecl()->containsDecl(ND))
697 return true;
698 }
699 }
700 }
701
702 return false;
703 }
704
705 std::unique_ptr<CorrectionCandidateCallback> clone() override {
706 return std::make_unique<RecordMemberExprValidatorCCC>(args&: *this);
707 }
708
709private:
710 const RecordDecl *const Record;
711};
712
713}
714
715static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
716 Expr *BaseExpr,
717 const RecordType *RTy,
718 SourceLocation OpLoc, bool IsArrow,
719 CXXScopeSpec &SS, bool HasTemplateArgs,
720 SourceLocation TemplateKWLoc,
721 TypoExpr *&TE) {
722 SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
723 RecordDecl *RDecl = RTy->getDecl();
724 if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
725 SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
726 diag::err_typecheck_incomplete_tag,
727 BaseRange))
728 return true;
729
730 if (HasTemplateArgs || TemplateKWLoc.isValid()) {
731 // LookupTemplateName doesn't expect these both to exist simultaneously.
732 QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
733
734 bool MOUS;
735 return SemaRef.LookupTemplateName(R, S: nullptr, SS, ObjectType, EnteringContext: false, MemberOfUnknownSpecialization&: MOUS,
736 RequiredTemplate: TemplateKWLoc);
737 }
738
739 DeclContext *DC = RDecl;
740 if (SS.isSet()) {
741 // If the member name was a qualified-id, look into the
742 // nested-name-specifier.
743 DC = SemaRef.computeDeclContext(SS, EnteringContext: false);
744
745 if (SemaRef.RequireCompleteDeclContext(SS, DC)) {
746 SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
747 << SS.getRange() << DC;
748 return true;
749 }
750
751 assert(DC && "Cannot handle non-computable dependent contexts in lookup");
752
753 if (!isa<TypeDecl>(Val: DC)) {
754 SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass)
755 << DC << SS.getRange();
756 return true;
757 }
758 }
759
760 // The record definition is complete, now look up the member.
761 SemaRef.LookupQualifiedName(R, LookupCtx: DC, SS);
762
763 if (!R.empty())
764 return false;
765
766 DeclarationName Typo = R.getLookupName();
767 SourceLocation TypoLoc = R.getNameLoc();
768
769 struct QueryState {
770 Sema &SemaRef;
771 DeclarationNameInfo NameInfo;
772 Sema::LookupNameKind LookupKind;
773 RedeclarationKind Redecl;
774 };
775 QueryState Q = {.SemaRef: R.getSema(), .NameInfo: R.getLookupNameInfo(), .LookupKind: R.getLookupKind(),
776 .Redecl: R.redeclarationKind()};
777 RecordMemberExprValidatorCCC CCC(RTy);
778 TE = SemaRef.CorrectTypoDelayed(
779 Typo: R.getLookupNameInfo(), LookupKind: R.getLookupKind(), S: nullptr, SS: &SS, CCC,
780 TDG: [=, &SemaRef](const TypoCorrection &TC) {
781 if (TC) {
782 assert(!TC.isKeyword() &&
783 "Got a keyword as a correction for a member!");
784 bool DroppedSpecifier =
785 TC.WillReplaceSpecifier() &&
786 Typo.getAsString() == TC.getAsString(LO: SemaRef.getLangOpts());
787 SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
788 << Typo << DC << DroppedSpecifier
789 << SS.getRange());
790 } else {
791 SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << DC << BaseRange;
792 }
793 },
794 TRC: [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {
795 LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl);
796 R.clear(); // Ensure there's no decls lingering in the shared state.
797 R.suppressDiagnostics();
798 R.setLookupName(TC.getCorrection());
799 for (NamedDecl *ND : TC)
800 R.addDecl(D: ND);
801 R.resolveKind();
802 return SemaRef.BuildMemberReferenceExpr(
803 Base: BaseExpr, BaseType: BaseExpr->getType(), OpLoc, IsArrow, SS, TemplateKWLoc: SourceLocation(),
804 FirstQualifierInScope: nullptr, R, TemplateArgs: nullptr, S: nullptr);
805 },
806 Mode: Sema::CTK_ErrorRecovery, MemberContext: DC);
807
808 return false;
809}
810
811static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
812 ExprResult &BaseExpr, bool &IsArrow,
813 SourceLocation OpLoc, CXXScopeSpec &SS,
814 Decl *ObjCImpDecl, bool HasTemplateArgs,
815 SourceLocation TemplateKWLoc);
816
817ExprResult
818Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
819 SourceLocation OpLoc, bool IsArrow,
820 CXXScopeSpec &SS,
821 SourceLocation TemplateKWLoc,
822 NamedDecl *FirstQualifierInScope,
823 const DeclarationNameInfo &NameInfo,
824 const TemplateArgumentListInfo *TemplateArgs,
825 const Scope *S,
826 ActOnMemberAccessExtraArgs *ExtraArgs) {
827 if (BaseType->isDependentType() ||
828 (SS.isSet() && isDependentScopeSpecifier(SS)) ||
829 NameInfo.getName().isDependentName())
830 return ActOnDependentMemberExpr(BaseExpr: Base, BaseType,
831 IsArrow, OpLoc,
832 SS, TemplateKWLoc, FirstQualifierInScope,
833 NameInfo, TemplateArgs);
834
835 LookupResult R(*this, NameInfo, LookupMemberName);
836
837 // Implicit member accesses.
838 if (!Base) {
839 TypoExpr *TE = nullptr;
840 QualType RecordTy = BaseType;
841 if (IsArrow) RecordTy = RecordTy->castAs<PointerType>()->getPointeeType();
842 if (LookupMemberExprInRecord(
843 SemaRef&: *this, R, BaseExpr: nullptr, RTy: RecordTy->castAs<RecordType>(), OpLoc, IsArrow,
844 SS, HasTemplateArgs: TemplateArgs != nullptr, TemplateKWLoc, TE))
845 return ExprError();
846 if (TE)
847 return TE;
848
849 // Explicit member accesses.
850 } else {
851 ExprResult BaseResult = Base;
852 ExprResult Result =
853 LookupMemberExpr(S&: *this, R, BaseExpr&: BaseResult, IsArrow, OpLoc, SS,
854 ObjCImpDecl: ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
855 HasTemplateArgs: TemplateArgs != nullptr, TemplateKWLoc);
856
857 if (BaseResult.isInvalid())
858 return ExprError();
859 Base = BaseResult.get();
860
861 if (Result.isInvalid())
862 return ExprError();
863
864 if (Result.get())
865 return Result;
866
867 // LookupMemberExpr can modify Base, and thus change BaseType
868 BaseType = Base->getType();
869 }
870
871 return BuildMemberReferenceExpr(Base, BaseType,
872 OpLoc, IsArrow, SS, TemplateKWLoc,
873 FirstQualifierInScope, R, TemplateArgs, S,
874 SuppressQualifierCheck: false, ExtraArgs);
875}
876
877ExprResult
878Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
879 SourceLocation loc,
880 IndirectFieldDecl *indirectField,
881 DeclAccessPair foundDecl,
882 Expr *baseObjectExpr,
883 SourceLocation opLoc) {
884 // First, build the expression that refers to the base object.
885
886 // Case 1: the base of the indirect field is not a field.
887 VarDecl *baseVariable = indirectField->getVarDecl();
888 CXXScopeSpec EmptySS;
889 if (baseVariable) {
890 assert(baseVariable->getType()->isRecordType());
891
892 // In principle we could have a member access expression that
893 // accesses an anonymous struct/union that's a static member of
894 // the base object's class. However, under the current standard,
895 // static data members cannot be anonymous structs or unions.
896 // Supporting this is as easy as building a MemberExpr here.
897 assert(!baseObjectExpr && "anonymous struct/union is static data member?");
898
899 DeclarationNameInfo baseNameInfo(DeclarationName(), loc);
900
901 ExprResult result
902 = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable);
903 if (result.isInvalid()) return ExprError();
904
905 baseObjectExpr = result.get();
906 }
907
908 assert((baseVariable || baseObjectExpr) &&
909 "referencing anonymous struct/union without a base variable or "
910 "expression");
911
912 // Build the implicit member references to the field of the
913 // anonymous struct/union.
914 Expr *result = baseObjectExpr;
915 IndirectFieldDecl::chain_iterator
916 FI = indirectField->chain_begin(), FEnd = indirectField->chain_end();
917
918 // Case 2: the base of the indirect field is a field and the user
919 // wrote a member expression.
920 if (!baseVariable) {
921 FieldDecl *field = cast<FieldDecl>(Val: *FI);
922
923 bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType();
924
925 // Make a nameInfo that properly uses the anonymous name.
926 DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
927
928 // Build the first member access in the chain with full information.
929 result =
930 BuildFieldReferenceExpr(BaseExpr: result, IsArrow: baseObjectIsPointer, OpLoc: SourceLocation(),
931 SS, Field: field, FoundDecl: foundDecl, MemberNameInfo: memberNameInfo)
932 .get();
933 if (!result)
934 return ExprError();
935 }
936
937 // In all cases, we should now skip the first declaration in the chain.
938 ++FI;
939
940 while (FI != FEnd) {
941 FieldDecl *field = cast<FieldDecl>(Val: *FI++);
942
943 // FIXME: these are somewhat meaningless
944 DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
945 DeclAccessPair fakeFoundDecl =
946 DeclAccessPair::make(D: field, AS: field->getAccess());
947
948 result =
949 BuildFieldReferenceExpr(BaseExpr: result, /*isarrow*/ IsArrow: false, OpLoc: SourceLocation(),
950 SS: (FI == FEnd ? SS : EmptySS), Field: field,
951 FoundDecl: fakeFoundDecl, MemberNameInfo: memberNameInfo)
952 .get();
953 }
954
955 return result;
956}
957
958static ExprResult
959BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
960 const CXXScopeSpec &SS,
961 MSPropertyDecl *PD,
962 const DeclarationNameInfo &NameInfo) {
963 // Property names are always simple identifiers and therefore never
964 // require any interesting additional storage.
965 return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,
966 S.Context.PseudoObjectTy, VK_LValue,
967 SS.getWithLocInContext(Context&: S.Context),
968 NameInfo.getLoc());
969}
970
971MemberExpr *Sema::BuildMemberExpr(
972 Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS,
973 SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
974 bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
975 QualType Ty, ExprValueKind VK, ExprObjectKind OK,
976 const TemplateArgumentListInfo *TemplateArgs) {
977 NestedNameSpecifierLoc NNS =
978 SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc();
979 return BuildMemberExpr(Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member,
980 FoundDecl, HadMultipleCandidates, MemberNameInfo, Ty,
981 VK, OK, TemplateArgs);
982}
983
984MemberExpr *Sema::BuildMemberExpr(
985 Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS,
986 SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
987 bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
988 QualType Ty, ExprValueKind VK, ExprObjectKind OK,
989 const TemplateArgumentListInfo *TemplateArgs) {
990 assert((!IsArrow || Base->isPRValue()) &&
991 "-> base must be a pointer prvalue");
992 MemberExpr *E =
993 MemberExpr::Create(C: Context, Base, IsArrow, OperatorLoc: OpLoc, QualifierLoc: NNS, TemplateKWLoc,
994 MemberDecl: Member, FoundDecl, MemberNameInfo, TemplateArgs, T: Ty,
995 VK, OK, NOUR: getNonOdrUseReasonInCurrentContext(D: Member));
996 E->setHadMultipleCandidates(HadMultipleCandidates);
997 MarkMemberReferenced(E);
998
999 // C++ [except.spec]p17:
1000 // An exception-specification is considered to be needed when:
1001 // - in an expression the function is the unique lookup result or the
1002 // selected member of a set of overloaded functions
1003 if (auto *FPT = Ty->getAs<FunctionProtoType>()) {
1004 if (isUnresolvedExceptionSpec(ESpecType: FPT->getExceptionSpecType())) {
1005 if (auto *NewFPT = ResolveExceptionSpec(Loc: MemberNameInfo.getLoc(), FPT))
1006 E->setType(Context.getQualifiedType(NewFPT, Ty.getQualifiers()));
1007 }
1008 }
1009
1010 return E;
1011}
1012
1013/// Determine if the given scope is within a function-try-block handler.
1014static bool IsInFnTryBlockHandler(const Scope *S) {
1015 // Walk the scope stack until finding a FnTryCatchScope, or leave the
1016 // function scope. If a FnTryCatchScope is found, check whether the TryScope
1017 // flag is set. If it is not, it's a function-try-block handler.
1018 for (; S != S->getFnParent(); S = S->getParent()) {
1019 if (S->isFnTryCatchScope())
1020 return (S->getFlags() & Scope::TryScope) != Scope::TryScope;
1021 }
1022 return false;
1023}
1024
1025ExprResult
1026Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
1027 SourceLocation OpLoc, bool IsArrow,
1028 const CXXScopeSpec &SS,
1029 SourceLocation TemplateKWLoc,
1030 NamedDecl *FirstQualifierInScope,
1031 LookupResult &R,
1032 const TemplateArgumentListInfo *TemplateArgs,
1033 const Scope *S,
1034 bool SuppressQualifierCheck,
1035 ActOnMemberAccessExtraArgs *ExtraArgs) {
1036 QualType BaseType = BaseExprType;
1037 if (IsArrow) {
1038 assert(BaseType->isPointerType());
1039 BaseType = BaseType->castAs<PointerType>()->getPointeeType();
1040 }
1041 R.setBaseObjectType(BaseType);
1042
1043 // C++1z [expr.ref]p2:
1044 // For the first option (dot) the first expression shall be a glvalue [...]
1045 if (!IsArrow && BaseExpr && BaseExpr->isPRValue()) {
1046 ExprResult Converted = TemporaryMaterializationConversion(E: BaseExpr);
1047 if (Converted.isInvalid())
1048 return ExprError();
1049 BaseExpr = Converted.get();
1050 }
1051
1052 const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
1053 DeclarationName MemberName = MemberNameInfo.getName();
1054 SourceLocation MemberLoc = MemberNameInfo.getLoc();
1055
1056 if (R.isAmbiguous())
1057 return ExprError();
1058
1059 // [except.handle]p10: Referring to any non-static member or base class of an
1060 // object in the handler for a function-try-block of a constructor or
1061 // destructor for that object results in undefined behavior.
1062 const auto *FD = getCurFunctionDecl();
1063 if (S && BaseExpr && FD &&
1064 (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
1065 isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) &&
1066 IsInFnTryBlockHandler(S))
1067 Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr)
1068 << isa<CXXDestructorDecl>(FD);
1069
1070 if (R.empty()) {
1071 // Rederive where we looked up.
1072 DeclContext *DC = (SS.isSet()
1073 ? computeDeclContext(SS, EnteringContext: false)
1074 : BaseType->castAs<RecordType>()->getDecl());
1075
1076 if (ExtraArgs) {
1077 ExprResult RetryExpr;
1078 if (!IsArrow && BaseExpr) {
1079 SFINAETrap Trap(*this, true);
1080 ParsedType ObjectType;
1081 bool MayBePseudoDestructor = false;
1082 RetryExpr = ActOnStartCXXMemberReference(S: getCurScope(), Base: BaseExpr,
1083 OpLoc, OpKind: tok::arrow, ObjectType,
1084 MayBePseudoDestructor);
1085 if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {
1086 CXXScopeSpec TempSS(SS);
1087 RetryExpr = ActOnMemberAccessExpr(
1088 S: ExtraArgs->S, Base: RetryExpr.get(), OpLoc, OpKind: tok::arrow, SS&: TempSS,
1089 TemplateKWLoc, Member&: ExtraArgs->Id, ObjCImpDecl: ExtraArgs->ObjCImpDecl);
1090 }
1091 if (Trap.hasErrorOccurred())
1092 RetryExpr = ExprError();
1093 }
1094 if (RetryExpr.isUsable()) {
1095 Diag(OpLoc, diag::err_no_member_overloaded_arrow)
1096 << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->");
1097 return RetryExpr;
1098 }
1099 }
1100
1101 Diag(R.getNameLoc(), diag::err_no_member)
1102 << MemberName << DC
1103 << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange());
1104 return ExprError();
1105 }
1106
1107 // Diagnose lookups that find only declarations from a non-base
1108 // type. This is possible for either qualified lookups (which may
1109 // have been qualified with an unrelated type) or implicit member
1110 // expressions (which were found with unqualified lookup and thus
1111 // may have come from an enclosing scope). Note that it's okay for
1112 // lookup to find declarations from a non-base type as long as those
1113 // aren't the ones picked by overload resolution.
1114 if ((SS.isSet() || !BaseExpr ||
1115 (isa<CXXThisExpr>(Val: BaseExpr) &&
1116 cast<CXXThisExpr>(Val: BaseExpr)->isImplicit())) &&
1117 !SuppressQualifierCheck &&
1118 CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
1119 return ExprError();
1120
1121 // Construct an unresolved result if we in fact got an unresolved
1122 // result.
1123 if (R.isOverloadedResult() || R.isUnresolvableResult()) {
1124 // Suppress any lookup-related diagnostics; we'll do these when we
1125 // pick a member.
1126 R.suppressDiagnostics();
1127
1128 UnresolvedMemberExpr *MemExpr
1129 = UnresolvedMemberExpr::Create(Context, HasUnresolvedUsing: R.isUnresolvableResult(),
1130 Base: BaseExpr, BaseType: BaseExprType,
1131 IsArrow, OperatorLoc: OpLoc,
1132 QualifierLoc: SS.getWithLocInContext(Context),
1133 TemplateKWLoc, MemberNameInfo,
1134 TemplateArgs, Begin: R.begin(), End: R.end());
1135
1136 return MemExpr;
1137 }
1138
1139 assert(R.isSingleResult());
1140 DeclAccessPair FoundDecl = R.begin().getPair();
1141 NamedDecl *MemberDecl = R.getFoundDecl();
1142
1143 // FIXME: diagnose the presence of template arguments now.
1144
1145 // If the decl being referenced had an error, return an error for this
1146 // sub-expr without emitting another error, in order to avoid cascading
1147 // error cases.
1148 if (MemberDecl->isInvalidDecl())
1149 return ExprError();
1150
1151 // Handle the implicit-member-access case.
1152 if (!BaseExpr) {
1153 // If this is not an instance member, convert to a non-member access.
1154 if (!MemberDecl->isCXXInstanceMember()) {
1155 // We might have a variable template specialization (or maybe one day a
1156 // member concept-id).
1157 if (TemplateArgs || TemplateKWLoc.isValid())
1158 return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/RequiresADL: false, TemplateArgs);
1159
1160 return BuildDeclarationNameExpr(SS, NameInfo: R.getLookupNameInfo(), D: MemberDecl,
1161 FoundD: FoundDecl, TemplateArgs);
1162 }
1163 SourceLocation Loc = R.getNameLoc();
1164 if (SS.getRange().isValid())
1165 Loc = SS.getRange().getBegin();
1166 BaseExpr = BuildCXXThisExpr(Loc, Type: BaseExprType, /*IsImplicit=*/true);
1167 }
1168
1169 // Check the use of this member.
1170 if (DiagnoseUseOfDecl(D: MemberDecl, Locs: MemberLoc))
1171 return ExprError();
1172
1173 if (FieldDecl *FD = dyn_cast<FieldDecl>(Val: MemberDecl))
1174 return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, Field: FD, FoundDecl,
1175 MemberNameInfo);
1176
1177 if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(Val: MemberDecl))
1178 return BuildMSPropertyRefExpr(S&: *this, BaseExpr, IsArrow, SS, PD,
1179 NameInfo: MemberNameInfo);
1180
1181 if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(Val: MemberDecl))
1182 // We may have found a field within an anonymous union or struct
1183 // (C++ [class.union]).
1184 return BuildAnonymousStructUnionMemberReference(SS, loc: MemberLoc, indirectField: FD,
1185 foundDecl: FoundDecl, baseObjectExpr: BaseExpr,
1186 opLoc: OpLoc);
1187
1188 if (VarDecl *Var = dyn_cast<VarDecl>(Val: MemberDecl)) {
1189 return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var,
1190 FoundDecl, /*HadMultipleCandidates=*/false,
1191 MemberNameInfo, Var->getType().getNonReferenceType(),
1192 VK_LValue, OK_Ordinary);
1193 }
1194
1195 if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(Val: MemberDecl)) {
1196 ExprValueKind valueKind;
1197 QualType type;
1198 if (MemberFn->isInstance()) {
1199 valueKind = VK_PRValue;
1200 type = Context.BoundMemberTy;
1201 } else {
1202 valueKind = VK_LValue;
1203 type = MemberFn->getType();
1204 }
1205
1206 return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc,
1207 MemberFn, FoundDecl, /*HadMultipleCandidates=*/false,
1208 MemberNameInfo, type, valueKind, OK_Ordinary);
1209 }
1210 assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
1211
1212 if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(Val: MemberDecl)) {
1213 return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Enum,
1214 FoundDecl, /*HadMultipleCandidates=*/false,
1215 MemberNameInfo, Enum->getType(), VK_PRValue,
1216 OK_Ordinary);
1217 }
1218
1219 if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(Val: MemberDecl)) {
1220 if (!TemplateArgs) {
1221 diagnoseMissingTemplateArguments(Name: TemplateName(VarTempl), Loc: MemberLoc);
1222 return ExprError();
1223 }
1224
1225 DeclResult VDecl = CheckVarTemplateId(Template: VarTempl, TemplateLoc: TemplateKWLoc,
1226 TemplateNameLoc: MemberNameInfo.getLoc(), TemplateArgs: *TemplateArgs);
1227 if (VDecl.isInvalid())
1228 return ExprError();
1229
1230 // Non-dependent member, but dependent template arguments.
1231 if (!VDecl.get())
1232 return ActOnDependentMemberExpr(
1233 BaseExpr, BaseType: BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc,
1234 FirstQualifierInScope, NameInfo: MemberNameInfo, TemplateArgs);
1235
1236 VarDecl *Var = cast<VarDecl>(Val: VDecl.get());
1237 if (!Var->getTemplateSpecializationKind())
1238 Var->setTemplateSpecializationKind(TSK: TSK_ImplicitInstantiation, PointOfInstantiation: MemberLoc);
1239
1240 return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var,
1241 FoundDecl, /*HadMultipleCandidates=*/false,
1242 MemberNameInfo, Var->getType().getNonReferenceType(),
1243 VK_LValue, OK_Ordinary, TemplateArgs);
1244 }
1245
1246 // We found something that we didn't expect. Complain.
1247 if (isa<TypeDecl>(MemberDecl))
1248 Diag(MemberLoc, diag::err_typecheck_member_reference_type)
1249 << MemberName << BaseType << int(IsArrow);
1250 else
1251 Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)
1252 << MemberName << BaseType << int(IsArrow);
1253
1254 Diag(MemberDecl->getLocation(), diag::note_member_declared_here)
1255 << MemberName;
1256 R.suppressDiagnostics();
1257 return ExprError();
1258}
1259
1260/// Given that normal member access failed on the given expression,
1261/// and given that the expression's type involves builtin-id or
1262/// builtin-Class, decide whether substituting in the redefinition
1263/// types would be profitable. The redefinition type is whatever
1264/// this translation unit tried to typedef to id/Class; we store
1265/// it to the side and then re-use it in places like this.
1266static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) {
1267 const ObjCObjectPointerType *opty
1268 = base.get()->getType()->getAs<ObjCObjectPointerType>();
1269 if (!opty) return false;
1270
1271 const ObjCObjectType *ty = opty->getObjectType();
1272
1273 QualType redef;
1274 if (ty->isObjCId()) {
1275 redef = S.Context.getObjCIdRedefinitionType();
1276 } else if (ty->isObjCClass()) {
1277 redef = S.Context.getObjCClassRedefinitionType();
1278 } else {
1279 return false;
1280 }
1281
1282 // Do the substitution as long as the redefinition type isn't just a
1283 // possibly-qualified pointer to builtin-id or builtin-Class again.
1284 opty = redef->getAs<ObjCObjectPointerType>();
1285 if (opty && !opty->getObjectType()->getInterface())
1286 return false;
1287
1288 base = S.ImpCastExprToType(E: base.get(), Type: redef, CK: CK_BitCast);
1289 return true;
1290}
1291
1292static bool isRecordType(QualType T) {
1293 return T->isRecordType();
1294}
1295static bool isPointerToRecordType(QualType T) {
1296 if (const PointerType *PT = T->getAs<PointerType>())
1297 return PT->getPointeeType()->isRecordType();
1298 return false;
1299}
1300
1301/// Perform conversions on the LHS of a member access expression.
1302ExprResult
1303Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) {
1304 if (IsArrow && !Base->getType()->isFunctionType())
1305 return DefaultFunctionArrayLvalueConversion(E: Base);
1306
1307 return CheckPlaceholderExpr(E: Base);
1308}
1309
1310/// Look up the given member of the given non-type-dependent
1311/// expression. This can return in one of two ways:
1312/// * If it returns a sentinel null-but-valid result, the caller will
1313/// assume that lookup was performed and the results written into
1314/// the provided structure. It will take over from there.
1315/// * Otherwise, the returned expression will be produced in place of
1316/// an ordinary member expression.
1317///
1318/// The ObjCImpDecl bit is a gross hack that will need to be properly
1319/// fixed for ObjC++.
1320static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
1321 ExprResult &BaseExpr, bool &IsArrow,
1322 SourceLocation OpLoc, CXXScopeSpec &SS,
1323 Decl *ObjCImpDecl, bool HasTemplateArgs,
1324 SourceLocation TemplateKWLoc) {
1325 assert(BaseExpr.get() && "no base expression");
1326
1327 // Perform default conversions.
1328 BaseExpr = S.PerformMemberExprBaseConversion(Base: BaseExpr.get(), IsArrow);
1329 if (BaseExpr.isInvalid())
1330 return ExprError();
1331
1332 QualType BaseType = BaseExpr.get()->getType();
1333 assert(!BaseType->isDependentType());
1334
1335 DeclarationName MemberName = R.getLookupName();
1336 SourceLocation MemberLoc = R.getNameLoc();
1337
1338 // For later type-checking purposes, turn arrow accesses into dot
1339 // accesses. The only access type we support that doesn't follow
1340 // the C equivalence "a->b === (*a).b" is ObjC property accesses,
1341 // and those never use arrows, so this is unaffected.
1342 if (IsArrow) {
1343 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
1344 BaseType = Ptr->getPointeeType();
1345 else if (const ObjCObjectPointerType *Ptr
1346 = BaseType->getAs<ObjCObjectPointerType>())
1347 BaseType = Ptr->getPointeeType();
1348 else if (BaseType->isRecordType()) {
1349 // Recover from arrow accesses to records, e.g.:
1350 // struct MyRecord foo;
1351 // foo->bar
1352 // This is actually well-formed in C++ if MyRecord has an
1353 // overloaded operator->, but that should have been dealt with
1354 // by now--or a diagnostic message already issued if a problem
1355 // was encountered while looking for the overloaded operator->.
1356 if (!S.getLangOpts().CPlusPlus) {
1357 S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
1358 << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
1359 << FixItHint::CreateReplacement(OpLoc, ".");
1360 }
1361 IsArrow = false;
1362 } else if (BaseType->isFunctionType()) {
1363 goto fail;
1364 } else {
1365 S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
1366 << BaseType << BaseExpr.get()->getSourceRange();
1367 return ExprError();
1368 }
1369 }
1370
1371 // If the base type is an atomic type, this access is undefined behavior per
1372 // C11 6.5.2.3p5. Instead of giving a typecheck error, we'll warn the user
1373 // about the UB and recover by converting the atomic lvalue into a non-atomic
1374 // lvalue. Because this is inherently unsafe as an atomic operation, the
1375 // warning defaults to an error.
1376 if (const auto *ATy = BaseType->getAs<AtomicType>()) {
1377 S.DiagRuntimeBehavior(OpLoc, nullptr,
1378 S.PDiag(diag::warn_atomic_member_access));
1379 BaseType = ATy->getValueType().getUnqualifiedType();
1380 BaseExpr = ImplicitCastExpr::Create(
1381 Context: S.Context, T: IsArrow ? S.Context.getPointerType(T: BaseType) : BaseType,
1382 Kind: CK_AtomicToNonAtomic, Operand: BaseExpr.get(), BasePath: nullptr,
1383 Cat: BaseExpr.get()->getValueKind(), FPO: FPOptionsOverride());
1384 }
1385
1386 // Handle field access to simple records.
1387 if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
1388 TypoExpr *TE = nullptr;
1389 if (LookupMemberExprInRecord(SemaRef&: S, R, BaseExpr: BaseExpr.get(), RTy, OpLoc, IsArrow, SS,
1390 HasTemplateArgs, TemplateKWLoc, TE))
1391 return ExprError();
1392
1393 // Returning valid-but-null is how we indicate to the caller that
1394 // the lookup result was filled in. If typo correction was attempted and
1395 // failed, the lookup result will have been cleared--that combined with the
1396 // valid-but-null ExprResult will trigger the appropriate diagnostics.
1397 return ExprResult(TE);
1398 }
1399
1400 // Handle ivar access to Objective-C objects.
1401 if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) {
1402 if (!SS.isEmpty() && !SS.isInvalid()) {
1403 S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
1404 << 1 << SS.getScopeRep()
1405 << FixItHint::CreateRemoval(SS.getRange());
1406 SS.clear();
1407 }
1408
1409 IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
1410
1411 // There are three cases for the base type:
1412 // - builtin id (qualified or unqualified)
1413 // - builtin Class (qualified or unqualified)
1414 // - an interface
1415 ObjCInterfaceDecl *IDecl = OTy->getInterface();
1416 if (!IDecl) {
1417 if (S.getLangOpts().ObjCAutoRefCount &&
1418 (OTy->isObjCId() || OTy->isObjCClass()))
1419 goto fail;
1420 // There's an implicit 'isa' ivar on all objects.
1421 // But we only actually find it this way on objects of type 'id',
1422 // apparently.
1423 if (OTy->isObjCId() && Member->isStr(Str: "isa"))
1424 return new (S.Context) ObjCIsaExpr(BaseExpr.get(), IsArrow, MemberLoc,
1425 OpLoc, S.Context.getObjCClassType());
1426 if (ShouldTryAgainWithRedefinitionType(S, base&: BaseExpr))
1427 return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
1428 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
1429 goto fail;
1430 }
1431
1432 if (S.RequireCompleteType(OpLoc, BaseType,
1433 diag::err_typecheck_incomplete_tag,
1434 BaseExpr.get()))
1435 return ExprError();
1436
1437 ObjCInterfaceDecl *ClassDeclared = nullptr;
1438 ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(IVarName: Member, ClassDeclared);
1439
1440 if (!IV) {
1441 // Attempt to correct for typos in ivar names.
1442 DeclFilterCCC<ObjCIvarDecl> Validator{};
1443 Validator.IsObjCIvarLookup = IsArrow;
1444 if (TypoCorrection Corrected = S.CorrectTypo(
1445 R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
1446 Validator, Sema::CTK_ErrorRecovery, IDecl)) {
1447 IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
1448 S.diagnoseTypo(
1449 Corrected,
1450 S.PDiag(diag::err_typecheck_member_reference_ivar_suggest)
1451 << IDecl->getDeclName() << MemberName);
1452
1453 // Figure out the class that declares the ivar.
1454 assert(!ClassDeclared);
1455
1456 Decl *D = cast<Decl>(IV->getDeclContext());
1457 if (auto *Category = dyn_cast<ObjCCategoryDecl>(D))
1458 D = Category->getClassInterface();
1459
1460 if (auto *Implementation = dyn_cast<ObjCImplementationDecl>(D))
1461 ClassDeclared = Implementation->getClassInterface();
1462 else if (auto *Interface = dyn_cast<ObjCInterfaceDecl>(D))
1463 ClassDeclared = Interface;
1464
1465 assert(ClassDeclared && "cannot query interface");
1466 } else {
1467 if (IsArrow &&
1468 IDecl->FindPropertyDeclaration(
1469 Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
1470 S.Diag(MemberLoc, diag::err_property_found_suggest)
1471 << Member << BaseExpr.get()->getType()
1472 << FixItHint::CreateReplacement(OpLoc, ".");
1473 return ExprError();
1474 }
1475
1476 S.Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
1477 << IDecl->getDeclName() << MemberName
1478 << BaseExpr.get()->getSourceRange();
1479 return ExprError();
1480 }
1481 }
1482
1483 assert(ClassDeclared);
1484
1485 // If the decl being referenced had an error, return an error for this
1486 // sub-expr without emitting another error, in order to avoid cascading
1487 // error cases.
1488 if (IV->isInvalidDecl())
1489 return ExprError();
1490
1491 // Check whether we can reference this field.
1492 if (S.DiagnoseUseOfDecl(IV, MemberLoc))
1493 return ExprError();
1494 if (IV->getAccessControl() != ObjCIvarDecl::Public &&
1495 IV->getAccessControl() != ObjCIvarDecl::Package) {
1496 ObjCInterfaceDecl *ClassOfMethodDecl = nullptr;
1497 if (ObjCMethodDecl *MD = S.getCurMethodDecl())
1498 ClassOfMethodDecl = MD->getClassInterface();
1499 else if (ObjCImpDecl && S.getCurFunctionDecl()) {
1500 // Case of a c-function declared inside an objc implementation.
1501 // FIXME: For a c-style function nested inside an objc implementation
1502 // class, there is no implementation context available, so we pass
1503 // down the context as argument to this routine. Ideally, this context
1504 // need be passed down in the AST node and somehow calculated from the
1505 // AST for a function decl.
1506 if (ObjCImplementationDecl *IMPD =
1507 dyn_cast<ObjCImplementationDecl>(Val: ObjCImpDecl))
1508 ClassOfMethodDecl = IMPD->getClassInterface();
1509 else if (ObjCCategoryImplDecl* CatImplClass =
1510 dyn_cast<ObjCCategoryImplDecl>(Val: ObjCImpDecl))
1511 ClassOfMethodDecl = CatImplClass->getClassInterface();
1512 }
1513 if (!S.getLangOpts().DebuggerSupport) {
1514 if (IV->getAccessControl() == ObjCIvarDecl::Private) {
1515 if (!declaresSameEntity(ClassDeclared, IDecl) ||
1516 !declaresSameEntity(ClassOfMethodDecl, ClassDeclared))
1517 S.Diag(MemberLoc, diag::err_private_ivar_access)
1518 << IV->getDeclName();
1519 } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
1520 // @protected
1521 S.Diag(MemberLoc, diag::err_protected_ivar_access)
1522 << IV->getDeclName();
1523 }
1524 }
1525 bool warn = true;
1526 if (S.getLangOpts().ObjCWeak) {
1527 Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts();
1528 if (UnaryOperator *UO = dyn_cast<UnaryOperator>(Val: BaseExp))
1529 if (UO->getOpcode() == UO_Deref)
1530 BaseExp = UO->getSubExpr()->IgnoreParenCasts();
1531
1532 if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(Val: BaseExp))
1533 if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
1534 S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access);
1535 warn = false;
1536 }
1537 }
1538 if (warn) {
1539 if (ObjCMethodDecl *MD = S.getCurMethodDecl()) {
1540 ObjCMethodFamily MF = MD->getMethodFamily();
1541 warn = (MF != OMF_init && MF != OMF_dealloc &&
1542 MF != OMF_finalize &&
1543 !S.IvarBacksCurrentMethodAccessor(IFace: IDecl, Method: MD, IV));
1544 }
1545 if (warn)
1546 S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
1547 }
1548
1549 ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr(
1550 IV, IV->getUsageType(objectType: BaseType), MemberLoc, OpLoc, BaseExpr.get(),
1551 IsArrow);
1552
1553 if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
1554 if (!S.isUnevaluatedContext() &&
1555 !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc))
1556 S.getCurFunction()->recordUseOfWeak(E: Result);
1557 }
1558
1559 return Result;
1560 }
1561
1562 // Objective-C property access.
1563 const ObjCObjectPointerType *OPT;
1564 if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) {
1565 if (!SS.isEmpty() && !SS.isInvalid()) {
1566 S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access)
1567 << 0 << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange());
1568 SS.clear();
1569 }
1570
1571 // This actually uses the base as an r-value.
1572 BaseExpr = S.DefaultLvalueConversion(E: BaseExpr.get());
1573 if (BaseExpr.isInvalid())
1574 return ExprError();
1575
1576 assert(S.Context.hasSameUnqualifiedType(BaseType,
1577 BaseExpr.get()->getType()));
1578
1579 IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
1580
1581 const ObjCObjectType *OT = OPT->getObjectType();
1582
1583 // id, with and without qualifiers.
1584 if (OT->isObjCId()) {
1585 // Check protocols on qualified interfaces.
1586 Selector Sel = S.PP.getSelectorTable().getNullarySelector(ID: Member);
1587 if (Decl *PMDecl =
1588 FindGetterSetterNameDecl(QIdTy: OPT, Member, Sel, Context&: S.Context)) {
1589 if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(Val: PMDecl)) {
1590 // Check the use of this declaration
1591 if (S.DiagnoseUseOfDecl(PD, MemberLoc))
1592 return ExprError();
1593
1594 return new (S.Context)
1595 ObjCPropertyRefExpr(PD, S.Context.PseudoObjectTy, VK_LValue,
1596 OK_ObjCProperty, MemberLoc, BaseExpr.get());
1597 }
1598
1599 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: PMDecl)) {
1600 Selector SetterSel =
1601 SelectorTable::constructSetterSelector(Idents&: S.PP.getIdentifierTable(),
1602 SelTable&: S.PP.getSelectorTable(),
1603 Name: Member);
1604 ObjCMethodDecl *SMD = nullptr;
1605 if (Decl *SDecl = FindGetterSetterNameDecl(QIdTy: OPT,
1606 /*Property id*/ Member: nullptr,
1607 Sel: SetterSel, Context&: S.Context))
1608 SMD = dyn_cast<ObjCMethodDecl>(Val: SDecl);
1609
1610 return new (S.Context)
1611 ObjCPropertyRefExpr(OMD, SMD, S.Context.PseudoObjectTy, VK_LValue,
1612 OK_ObjCProperty, MemberLoc, BaseExpr.get());
1613 }
1614 }
1615 // Use of id.member can only be for a property reference. Do not
1616 // use the 'id' redefinition in this case.
1617 if (IsArrow && ShouldTryAgainWithRedefinitionType(S, base&: BaseExpr))
1618 return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
1619 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
1620
1621 return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
1622 << MemberName << BaseType);
1623 }
1624
1625 // 'Class', unqualified only.
1626 if (OT->isObjCClass()) {
1627 // Only works in a method declaration (??!).
1628 ObjCMethodDecl *MD = S.getCurMethodDecl();
1629 if (!MD) {
1630 if (ShouldTryAgainWithRedefinitionType(S, base&: BaseExpr))
1631 return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
1632 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
1633
1634 goto fail;
1635 }
1636
1637 // Also must look for a getter name which uses property syntax.
1638 Selector Sel = S.PP.getSelectorTable().getNullarySelector(ID: Member);
1639 ObjCInterfaceDecl *IFace = MD->getClassInterface();
1640 if (!IFace)
1641 goto fail;
1642
1643 ObjCMethodDecl *Getter;
1644 if ((Getter = IFace->lookupClassMethod(Sel))) {
1645 // Check the use of this method.
1646 if (S.DiagnoseUseOfDecl(Getter, MemberLoc))
1647 return ExprError();
1648 } else
1649 Getter = IFace->lookupPrivateMethod(Sel, Instance: false);
1650 // If we found a getter then this may be a valid dot-reference, we
1651 // will look for the matching setter, in case it is needed.
1652 Selector SetterSel =
1653 SelectorTable::constructSetterSelector(Idents&: S.PP.getIdentifierTable(),
1654 SelTable&: S.PP.getSelectorTable(),
1655 Name: Member);
1656 ObjCMethodDecl *Setter = IFace->lookupClassMethod(Sel: SetterSel);
1657 if (!Setter) {
1658 // If this reference is in an @implementation, also check for 'private'
1659 // methods.
1660 Setter = IFace->lookupPrivateMethod(Sel: SetterSel, Instance: false);
1661 }
1662
1663 if (Setter && S.DiagnoseUseOfDecl(Setter, MemberLoc))
1664 return ExprError();
1665
1666 if (Getter || Setter) {
1667 return new (S.Context) ObjCPropertyRefExpr(
1668 Getter, Setter, S.Context.PseudoObjectTy, VK_LValue,
1669 OK_ObjCProperty, MemberLoc, BaseExpr.get());
1670 }
1671
1672 if (ShouldTryAgainWithRedefinitionType(S, base&: BaseExpr))
1673 return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
1674 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
1675
1676 return ExprError(S.Diag(MemberLoc, diag::err_property_not_found)
1677 << MemberName << BaseType);
1678 }
1679
1680 // Normal property access.
1681 return S.HandleExprPropertyRefExpr(OPT, BaseExpr: BaseExpr.get(), OpLoc, MemberName,
1682 MemberLoc, SuperLoc: SourceLocation(), SuperType: QualType(),
1683 Super: false);
1684 }
1685
1686 if (BaseType->isExtVectorBoolType()) {
1687 // We disallow element access for ext_vector_type bool. There is no way to
1688 // materialize a reference to a vector element as a pointer (each element is
1689 // one bit in the vector).
1690 S.Diag(R.getNameLoc(), diag::err_ext_vector_component_name_illegal)
1691 << MemberName
1692 << (BaseExpr.get() ? BaseExpr.get()->getSourceRange() : SourceRange());
1693 return ExprError();
1694 }
1695
1696 // Handle 'field access' to vectors, such as 'V.xx'.
1697 if (BaseType->isExtVectorType()) {
1698 // FIXME: this expr should store IsArrow.
1699 IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
1700 ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind());
1701 QualType ret = CheckExtVectorComponent(S, baseType: BaseType, VK, OpLoc,
1702 CompName: Member, CompLoc: MemberLoc);
1703 if (ret.isNull())
1704 return ExprError();
1705 Qualifiers BaseQ =
1706 S.Context.getCanonicalType(T: BaseExpr.get()->getType()).getQualifiers();
1707 ret = S.Context.getQualifiedType(T: ret, Qs: BaseQ);
1708
1709 return new (S.Context)
1710 ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc);
1711 }
1712
1713 // Adjust builtin-sel to the appropriate redefinition type if that's
1714 // not just a pointer to builtin-sel again.
1715 if (IsArrow && BaseType->isSpecificBuiltinType(K: BuiltinType::ObjCSel) &&
1716 !S.Context.getObjCSelRedefinitionType()->isObjCSelType()) {
1717 BaseExpr = S.ImpCastExprToType(
1718 E: BaseExpr.get(), Type: S.Context.getObjCSelRedefinitionType(), CK: CK_BitCast);
1719 return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
1720 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
1721 }
1722
1723 // Failure cases.
1724 fail:
1725
1726 // Recover from dot accesses to pointers, e.g.:
1727 // type *foo;
1728 // foo.bar
1729 // This is actually well-formed in two cases:
1730 // - 'type' is an Objective C type
1731 // - 'bar' is a pseudo-destructor name which happens to refer to
1732 // the appropriate pointer type
1733 if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
1734 if (!IsArrow && Ptr->getPointeeType()->isRecordType() &&
1735 MemberName.getNameKind() != DeclarationName::CXXDestructorName) {
1736 S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
1737 << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
1738 << FixItHint::CreateReplacement(OpLoc, "->");
1739
1740 if (S.isSFINAEContext())
1741 return ExprError();
1742
1743 // Recurse as an -> access.
1744 IsArrow = true;
1745 return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
1746 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
1747 }
1748 }
1749
1750 // If the user is trying to apply -> or . to a function name, it's probably
1751 // because they forgot parentheses to call that function.
1752 if (S.tryToRecoverWithCall(
1753 BaseExpr, S.PDiag(diag::err_member_reference_needs_call),
1754 /*complain*/ false,
1755 IsArrow ? &isPointerToRecordType : &isRecordType)) {
1756 if (BaseExpr.isInvalid())
1757 return ExprError();
1758 BaseExpr = S.DefaultFunctionArrayConversion(E: BaseExpr.get());
1759 return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
1760 ObjCImpDecl, HasTemplateArgs, TemplateKWLoc);
1761 }
1762
1763 // HLSL supports implicit conversion of scalar types to single element vector
1764 // rvalues in member expressions.
1765 if (S.getLangOpts().HLSL && BaseType->isScalarType()) {
1766 QualType VectorTy = S.Context.getExtVectorType(VectorType: BaseType, NumElts: 1);
1767 BaseExpr = S.ImpCastExprToType(E: BaseExpr.get(), Type: VectorTy, CK: CK_VectorSplat,
1768 VK: BaseExpr.get()->getValueKind());
1769 return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl,
1770 HasTemplateArgs, TemplateKWLoc);
1771 }
1772
1773 S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union)
1774 << BaseType << BaseExpr.get()->getSourceRange() << MemberLoc;
1775
1776 return ExprError();
1777}
1778
1779/// The main callback when the parser finds something like
1780/// expression . [nested-name-specifier] identifier
1781/// expression -> [nested-name-specifier] identifier
1782/// where 'identifier' encompasses a fairly broad spectrum of
1783/// possibilities, including destructor and operator references.
1784///
1785/// \param OpKind either tok::arrow or tok::period
1786/// \param ObjCImpDecl the current Objective-C \@implementation
1787/// decl; this is an ugly hack around the fact that Objective-C
1788/// \@implementations aren't properly put in the context chain
1789ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
1790 SourceLocation OpLoc,
1791 tok::TokenKind OpKind,
1792 CXXScopeSpec &SS,
1793 SourceLocation TemplateKWLoc,
1794 UnqualifiedId &Id,
1795 Decl *ObjCImpDecl) {
1796 if (SS.isSet() && SS.isInvalid())
1797 return ExprError();
1798
1799 // Warn about the explicit constructor calls Microsoft extension.
1800 if (getLangOpts().MicrosoftExt &&
1801 Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
1802 Diag(Id.getSourceRange().getBegin(),
1803 diag::ext_ms_explicit_constructor_call);
1804
1805 TemplateArgumentListInfo TemplateArgsBuffer;
1806
1807 // Decompose the name into its component parts.
1808 DeclarationNameInfo NameInfo;
1809 const TemplateArgumentListInfo *TemplateArgs;
1810 DecomposeUnqualifiedId(Id, Buffer&: TemplateArgsBuffer,
1811 NameInfo, TemplateArgs);
1812
1813 DeclarationName Name = NameInfo.getName();
1814 bool IsArrow = (OpKind == tok::arrow);
1815
1816 if (getLangOpts().HLSL && IsArrow)
1817 return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2);
1818
1819 NamedDecl *FirstQualifierInScope
1820 = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, NNS: SS.getScopeRep()));
1821
1822 // This is a postfix expression, so get rid of ParenListExprs.
1823 ExprResult Result = MaybeConvertParenListExprToParenExpr(S, ME: Base);
1824 if (Result.isInvalid()) return ExprError();
1825 Base = Result.get();
1826
1827 if (Base->getType()->isDependentType() || Name.isDependentName() ||
1828 isDependentScopeSpecifier(SS)) {
1829 return ActOnDependentMemberExpr(BaseExpr: Base, BaseType: Base->getType(), IsArrow, OpLoc, SS,
1830 TemplateKWLoc, FirstQualifierInScope,
1831 NameInfo, TemplateArgs);
1832 }
1833
1834 ActOnMemberAccessExtraArgs ExtraArgs = {.S: S, .Id: Id, .ObjCImpDecl: ObjCImpDecl};
1835 ExprResult Res = BuildMemberReferenceExpr(
1836 Base, BaseType: Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc,
1837 FirstQualifierInScope, NameInfo, TemplateArgs, S, ExtraArgs: &ExtraArgs);
1838
1839 if (!Res.isInvalid() && isa<MemberExpr>(Val: Res.get()))
1840 CheckMemberAccessOfNoDeref(E: cast<MemberExpr>(Val: Res.get()));
1841
1842 return Res;
1843}
1844
1845void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {
1846 if (isUnevaluatedContext())
1847 return;
1848
1849 QualType ResultTy = E->getType();
1850
1851 // Member accesses have four cases:
1852 // 1: non-array member via "->": dereferences
1853 // 2: non-array member via ".": nothing interesting happens
1854 // 3: array member access via "->": nothing interesting happens
1855 // (this returns an array lvalue and does not actually dereference memory)
1856 // 4: array member access via ".": *adds* a layer of indirection
1857 if (ResultTy->isArrayType()) {
1858 if (!E->isArrow()) {
1859 // This might be something like:
1860 // (*structPtr).arrayMember
1861 // which behaves roughly like:
1862 // &(*structPtr).pointerMember
1863 // in that the apparent dereference in the base expression does not
1864 // actually happen.
1865 CheckAddressOfNoDeref(E: E->getBase());
1866 }
1867 } else if (E->isArrow()) {
1868 if (const auto *Ptr = dyn_cast<PointerType>(
1869 Val: E->getBase()->getType().getDesugaredType(Context))) {
1870 if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
1871 ExprEvalContexts.back().PossibleDerefs.insert(E);
1872 }
1873 }
1874}
1875
1876ExprResult
1877Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
1878 SourceLocation OpLoc, const CXXScopeSpec &SS,
1879 FieldDecl *Field, DeclAccessPair FoundDecl,
1880 const DeclarationNameInfo &MemberNameInfo) {
1881 // x.a is an l-value if 'a' has a reference type. Otherwise:
1882 // x.a is an l-value/x-value/pr-value if the base is (and note
1883 // that *x is always an l-value), except that if the base isn't
1884 // an ordinary object then we must have an rvalue.
1885 ExprValueKind VK = VK_LValue;
1886 ExprObjectKind OK = OK_Ordinary;
1887 if (!IsArrow) {
1888 if (BaseExpr->getObjectKind() == OK_Ordinary)
1889 VK = BaseExpr->getValueKind();
1890 else
1891 VK = VK_PRValue;
1892 }
1893 if (VK != VK_PRValue && Field->isBitField())
1894 OK = OK_BitField;
1895
1896 // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
1897 QualType MemberType = Field->getType();
1898 if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
1899 MemberType = Ref->getPointeeType();
1900 VK = VK_LValue;
1901 } else {
1902 QualType BaseType = BaseExpr->getType();
1903 if (IsArrow) BaseType = BaseType->castAs<PointerType>()->getPointeeType();
1904
1905 Qualifiers BaseQuals = BaseType.getQualifiers();
1906
1907 // GC attributes are never picked up by members.
1908 BaseQuals.removeObjCGCAttr();
1909
1910 // CVR attributes from the base are picked up by members,
1911 // except that 'mutable' members don't pick up 'const'.
1912 if (Field->isMutable()) BaseQuals.removeConst();
1913
1914 Qualifiers MemberQuals =
1915 Context.getCanonicalType(T: MemberType).getQualifiers();
1916
1917 assert(!MemberQuals.hasAddressSpace());
1918
1919 Qualifiers Combined = BaseQuals + MemberQuals;
1920 if (Combined != MemberQuals)
1921 MemberType = Context.getQualifiedType(T: MemberType, Qs: Combined);
1922
1923 // Pick up NoDeref from the base in case we end up using AddrOf on the
1924 // result. E.g. the expression
1925 // &someNoDerefPtr->pointerMember
1926 // should be a noderef pointer again.
1927 if (BaseType->hasAttr(attr::NoDeref))
1928 MemberType =
1929 Context.getAttributedType(attr::NoDeref, MemberType, MemberType);
1930 }
1931
1932 auto *CurMethod = dyn_cast<CXXMethodDecl>(Val: CurContext);
1933 if (!(CurMethod && CurMethod->isDefaulted()))
1934 UnusedPrivateFields.remove(Field);
1935
1936 ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
1937 FoundDecl, Field);
1938 if (Base.isInvalid())
1939 return ExprError();
1940
1941 // Build a reference to a private copy for non-static data members in
1942 // non-static member functions, privatized by OpenMP constructs.
1943 if (getLangOpts().OpenMP && IsArrow &&
1944 !CurContext->isDependentContext() &&
1945 isa<CXXThisExpr>(Val: Base.get()->IgnoreParenImpCasts())) {
1946 if (auto *PrivateCopy = OpenMP().isOpenMPCapturedDecl(Field)) {
1947 return OpenMP().getOpenMPCapturedExpr(Capture: PrivateCopy, VK, OK,
1948 Loc: MemberNameInfo.getLoc());
1949 }
1950 }
1951
1952 return BuildMemberExpr(Base.get(), IsArrow, OpLoc, &SS,
1953 /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,
1954 /*HadMultipleCandidates=*/false, MemberNameInfo,
1955 MemberType, VK, OK);
1956}
1957
1958/// Builds an implicit member access expression. The current context
1959/// is known to be an instance method, and the given unqualified lookup
1960/// set is known to contain only instance members, at least one of which
1961/// is from an appropriate type.
1962ExprResult
1963Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
1964 SourceLocation TemplateKWLoc,
1965 LookupResult &R,
1966 const TemplateArgumentListInfo *TemplateArgs,
1967 bool IsKnownInstance, const Scope *S) {
1968 assert(!R.empty() && !R.isAmbiguous());
1969
1970 SourceLocation loc = R.getNameLoc();
1971
1972 // If this is known to be an instance access, go ahead and build an
1973 // implicit 'this' expression now.
1974 QualType ThisTy = getCurrentThisType();
1975 assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
1976
1977 Expr *baseExpr = nullptr; // null signifies implicit access
1978 if (IsKnownInstance) {
1979 SourceLocation Loc = R.getNameLoc();
1980 if (SS.getRange().isValid())
1981 Loc = SS.getRange().getBegin();
1982 baseExpr = BuildCXXThisExpr(Loc: loc, Type: ThisTy, /*IsImplicit=*/true);
1983 }
1984
1985 return BuildMemberReferenceExpr(
1986 BaseExpr: baseExpr, BaseExprType: ThisTy,
1987 /*OpLoc=*/SourceLocation(),
1988 /*IsArrow=*/!getLangOpts().HLSL, SS, TemplateKWLoc,
1989 /*FirstQualifierInScope=*/nullptr, R, TemplateArgs, S);
1990}
1991

source code of clang/lib/Sema/SemaExprMember.cpp