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