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