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