|
@@ -2482,23 +2482,20 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr(
|
|
return BuildDeclarationNameExpr(SS, R, /* ADL */ false);
|
|
return BuildDeclarationNameExpr(SS, R, /* ADL */ false);
|
|
}
|
|
}
|
|
|
|
|
|
-/// LookupInObjCMethod - The parser has read a name in, and Sema has
|
|
|
|
-/// detected that we're currently inside an ObjC method. Perform some
|
|
|
|
-/// additional lookup.
|
|
|
|
|
|
+/// The parser has read a name in, and Sema has detected that we're currently
|
|
|
|
+/// inside an ObjC method. Perform some additional checks and determine if we
|
|
|
|
+/// should form a reference to an ivar.
|
|
///
|
|
///
|
|
/// Ideally, most of this would be done by lookup, but there's
|
|
/// Ideally, most of this would be done by lookup, but there's
|
|
/// actually quite a lot of extra work involved.
|
|
/// actually quite a lot of extra work involved.
|
|
-///
|
|
|
|
-/// Returns a null sentinel to indicate trivial success.
|
|
|
|
-ExprResult
|
|
|
|
-Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
|
|
|
|
- IdentifierInfo *II, bool AllowBuiltinCreation) {
|
|
|
|
|
|
+DeclResult Sema::LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
|
|
|
|
+ IdentifierInfo *II) {
|
|
SourceLocation Loc = Lookup.getNameLoc();
|
|
SourceLocation Loc = Lookup.getNameLoc();
|
|
ObjCMethodDecl *CurMethod = getCurMethodDecl();
|
|
ObjCMethodDecl *CurMethod = getCurMethodDecl();
|
|
|
|
|
|
// Check for error condition which is already reported.
|
|
// Check for error condition which is already reported.
|
|
if (!CurMethod)
|
|
if (!CurMethod)
|
|
- return ExprError();
|
|
|
|
|
|
+ return DeclResult(true);
|
|
|
|
|
|
// There are two cases to handle here. 1) scoped lookup could have failed,
|
|
// There are two cases to handle here. 1) scoped lookup could have failed,
|
|
// in which case we should look for an ivar. 2) scoped lookup could have
|
|
// in which case we should look for an ivar. 2) scoped lookup could have
|
|
@@ -2526,18 +2523,10 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
|
|
ObjCIvarDecl *IV = nullptr;
|
|
ObjCIvarDecl *IV = nullptr;
|
|
if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {
|
|
if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {
|
|
// Diagnose using an ivar in a class method.
|
|
// Diagnose using an ivar in a class method.
|
|
- if (IsClassMethod)
|
|
|
|
- return ExprError(Diag(Loc, diag::err_ivar_use_in_class_method)
|
|
|
|
- << IV->getDeclName());
|
|
|
|
-
|
|
|
|
- // If we're referencing an invalid decl, just return this as a silent
|
|
|
|
- // error node. The error diagnostic was already emitted on the decl.
|
|
|
|
- if (IV->isInvalidDecl())
|
|
|
|
- return ExprError();
|
|
|
|
-
|
|
|
|
- // Check if referencing a field with __attribute__((deprecated)).
|
|
|
|
- if (DiagnoseUseOfDecl(IV, Loc))
|
|
|
|
- return ExprError();
|
|
|
|
|
|
+ if (IsClassMethod) {
|
|
|
|
+ Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName();
|
|
|
|
+ return DeclResult(true);
|
|
|
|
+ }
|
|
|
|
|
|
// Diagnose the use of an ivar outside of the declaring class.
|
|
// Diagnose the use of an ivar outside of the declaring class.
|
|
if (IV->getAccessControl() == ObjCIvarDecl::Private &&
|
|
if (IV->getAccessControl() == ObjCIvarDecl::Private &&
|
|
@@ -2545,46 +2534,8 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
|
|
!getLangOpts().DebuggerSupport)
|
|
!getLangOpts().DebuggerSupport)
|
|
Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName();
|
|
Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName();
|
|
|
|
|
|
- // FIXME: This should use a new expr for a direct reference, don't
|
|
|
|
- // turn this into Self->ivar, just return a BareIVarExpr or something.
|
|
|
|
- IdentifierInfo &II = Context.Idents.get("self");
|
|
|
|
- UnqualifiedId SelfName;
|
|
|
|
- SelfName.setIdentifier(&II, SourceLocation());
|
|
|
|
- SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
|
|
|
|
- CXXScopeSpec SelfScopeSpec;
|
|
|
|
- SourceLocation TemplateKWLoc;
|
|
|
|
- ExprResult SelfExpr =
|
|
|
|
- ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName,
|
|
|
|
- /*HasTrailingLParen=*/false,
|
|
|
|
- /*IsAddressOfOperand=*/false);
|
|
|
|
- if (SelfExpr.isInvalid())
|
|
|
|
- return ExprError();
|
|
|
|
-
|
|
|
|
- SelfExpr = DefaultLvalueConversion(SelfExpr.get());
|
|
|
|
- if (SelfExpr.isInvalid())
|
|
|
|
- return ExprError();
|
|
|
|
-
|
|
|
|
- MarkAnyDeclReferenced(Loc, IV, true);
|
|
|
|
-
|
|
|
|
- ObjCMethodFamily MF = CurMethod->getMethodFamily();
|
|
|
|
- if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
|
|
|
|
- !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
|
|
|
|
- Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
|
|
|
|
-
|
|
|
|
- ObjCIvarRefExpr *Result = new (Context)
|
|
|
|
- ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc,
|
|
|
|
- IV->getLocation(), SelfExpr.get(), true, true);
|
|
|
|
-
|
|
|
|
- if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
|
|
|
|
- if (!isUnevaluatedContext() &&
|
|
|
|
- !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
|
|
|
|
- getCurFunction()->recordUseOfWeak(Result);
|
|
|
|
- }
|
|
|
|
- if (getLangOpts().ObjCAutoRefCount)
|
|
|
|
- if (const BlockDecl *BD = CurContext->getInnermostBlockDecl())
|
|
|
|
- ImplicitlyRetainedSelfLocs.push_back({Loc, BD});
|
|
|
|
-
|
|
|
|
- return Result;
|
|
|
|
|
|
+ // Success.
|
|
|
|
+ return IV;
|
|
}
|
|
}
|
|
} else if (CurMethod->isInstanceMethod()) {
|
|
} else if (CurMethod->isInstanceMethod()) {
|
|
// We should warn if a local variable hides an ivar.
|
|
// We should warn if a local variable hides an ivar.
|
|
@@ -2599,25 +2550,97 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
|
|
} else if (Lookup.isSingleResult() &&
|
|
} else if (Lookup.isSingleResult() &&
|
|
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {
|
|
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {
|
|
// If accessing a stand-alone ivar in a class method, this is an error.
|
|
// If accessing a stand-alone ivar in a class method, this is an error.
|
|
- if (const ObjCIvarDecl *IV = dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl()))
|
|
|
|
- return ExprError(Diag(Loc, diag::err_ivar_use_in_class_method)
|
|
|
|
- << IV->getDeclName());
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (Lookup.empty() && II && AllowBuiltinCreation) {
|
|
|
|
- // FIXME. Consolidate this with similar code in LookupName.
|
|
|
|
- if (unsigned BuiltinID = II->getBuiltinID()) {
|
|
|
|
- if (!(getLangOpts().CPlusPlus &&
|
|
|
|
- Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))) {
|
|
|
|
- NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
|
|
|
|
- S, Lookup.isForRedeclaration(),
|
|
|
|
- Lookup.getNameLoc());
|
|
|
|
- if (D) Lookup.addDecl(D);
|
|
|
|
- }
|
|
|
|
|
|
+ if (const ObjCIvarDecl *IV =
|
|
|
|
+ dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl())) {
|
|
|
|
+ Diag(Loc, diag::err_ivar_use_in_class_method) << IV->getDeclName();
|
|
|
|
+ return DeclResult(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Didn't encounter an error, didn't find an ivar.
|
|
|
|
+ return DeclResult(false);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+ExprResult Sema::BuildIvarRefExpr(Scope *S, SourceLocation Loc,
|
|
|
|
+ ObjCIvarDecl *IV) {
|
|
|
|
+ ObjCMethodDecl *CurMethod = getCurMethodDecl();
|
|
|
|
+ assert(CurMethod && CurMethod->isInstanceMethod() &&
|
|
|
|
+ "should not reference ivar from this context");
|
|
|
|
+
|
|
|
|
+ ObjCInterfaceDecl *IFace = CurMethod->getClassInterface();
|
|
|
|
+ assert(IFace && "should not reference ivar from this context");
|
|
|
|
+
|
|
|
|
+ // If we're referencing an invalid decl, just return this as a silent
|
|
|
|
+ // error node. The error diagnostic was already emitted on the decl.
|
|
|
|
+ if (IV->isInvalidDecl())
|
|
|
|
+ return ExprError();
|
|
|
|
+
|
|
|
|
+ // Check if referencing a field with __attribute__((deprecated)).
|
|
|
|
+ if (DiagnoseUseOfDecl(IV, Loc))
|
|
|
|
+ return ExprError();
|
|
|
|
+
|
|
|
|
+ // FIXME: This should use a new expr for a direct reference, don't
|
|
|
|
+ // turn this into Self->ivar, just return a BareIVarExpr or something.
|
|
|
|
+ IdentifierInfo &II = Context.Idents.get("self");
|
|
|
|
+ UnqualifiedId SelfName;
|
|
|
|
+ SelfName.setIdentifier(&II, SourceLocation());
|
|
|
|
+ SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
|
|
|
|
+ CXXScopeSpec SelfScopeSpec;
|
|
|
|
+ SourceLocation TemplateKWLoc;
|
|
|
|
+ ExprResult SelfExpr =
|
|
|
|
+ ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc, SelfName,
|
|
|
|
+ /*HasTrailingLParen=*/false,
|
|
|
|
+ /*IsAddressOfOperand=*/false);
|
|
|
|
+ if (SelfExpr.isInvalid())
|
|
|
|
+ return ExprError();
|
|
|
|
+
|
|
|
|
+ SelfExpr = DefaultLvalueConversion(SelfExpr.get());
|
|
|
|
+ if (SelfExpr.isInvalid())
|
|
|
|
+ return ExprError();
|
|
|
|
+
|
|
|
|
+ MarkAnyDeclReferenced(Loc, IV, true);
|
|
|
|
+
|
|
|
|
+ ObjCMethodFamily MF = CurMethod->getMethodFamily();
|
|
|
|
+ if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
|
|
|
|
+ !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
|
|
|
|
+ Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
|
|
|
|
+
|
|
|
|
+ ObjCIvarRefExpr *Result = new (Context)
|
|
|
|
+ ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc,
|
|
|
|
+ IV->getLocation(), SelfExpr.get(), true, true);
|
|
|
|
+
|
|
|
|
+ if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
|
|
|
|
+ if (!isUnevaluatedContext() &&
|
|
|
|
+ !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
|
|
|
|
+ getCurFunction()->recordUseOfWeak(Result);
|
|
|
|
+ }
|
|
|
|
+ if (getLangOpts().ObjCAutoRefCount)
|
|
|
|
+ if (const BlockDecl *BD = CurContext->getInnermostBlockDecl())
|
|
|
|
+ ImplicitlyRetainedSelfLocs.push_back({Loc, BD});
|
|
|
|
+
|
|
|
|
+ return Result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// The parser has read a name in, and Sema has detected that we're currently
|
|
|
|
+/// inside an ObjC method. Perform some additional checks and determine if we
|
|
|
|
+/// should form a reference to an ivar. If so, build an expression referencing
|
|
|
|
+/// that ivar.
|
|
|
|
+ExprResult
|
|
|
|
+Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
|
|
|
|
+ IdentifierInfo *II, bool AllowBuiltinCreation) {
|
|
|
|
+ // FIXME: Integrate this lookup step into LookupParsedName.
|
|
|
|
+ DeclResult Ivar = LookupIvarInObjCMethod(Lookup, S, II);
|
|
|
|
+ if (Ivar.isInvalid())
|
|
|
|
+ return ExprError();
|
|
|
|
+ if (Ivar.isUsable())
|
|
|
|
+ return BuildIvarRefExpr(S, Lookup.getNameLoc(),
|
|
|
|
+ cast<ObjCIvarDecl>(Ivar.get()));
|
|
|
|
+
|
|
|
|
+ if (Lookup.empty() && II && AllowBuiltinCreation)
|
|
|
|
+ LookupBuiltin(Lookup);
|
|
|
|
+
|
|
// Sentinel value saying that we didn't do anything special.
|
|
// Sentinel value saying that we didn't do anything special.
|
|
- return ExprResult((Expr *)nullptr);
|
|
|
|
|
|
+ return ExprResult(false);
|
|
}
|
|
}
|
|
|
|
|
|
/// Cast a base object to a member's actual type.
|
|
/// Cast a base object to a member's actual type.
|