mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-03 14:22:23 +00:00
Redeclare Objective-C property accessors inside the ObjCImplDecl in which they are synthesized.
This patch is motivated by (and factored out from) https://reviews.llvm.org/D66121 which is a debug info bugfix. Starting with DWARF 5 all Objective-C methods are nested inside their containing type, and that patch implements this for synthesized Objective-C properties. 1. SemaObjCProperty populates a list of synthesized accessors that may need to inserted into an ObjCImplDecl. 2. SemaDeclObjC::ActOnEnd inserts forward-declarations for all accessors for which no override was provided into their ObjCImplDecl. This patch does *not* synthesize AST function *bodies*. Moving that code from the static analyzer into Sema may be a good idea though. 3. Places that expect all methods to have bodies have been updated. I did not update the static analyzer's inliner for synthesized properties to point back to the property declaration (see test/Analysis/Inputs/expected-plists/nullability-notes.m.plist), which I believed to be more bug than a feature. Differential Revision: https://reviews.llvm.org/D68108 rdar://problem/53782400
This commit is contained in:
parent
8d22100f66
commit
2073dd2da7
@ -1590,6 +1590,9 @@ class DeclContext {
|
|||||||
/// True if this method is the getter or setter for an explicit property.
|
/// True if this method is the getter or setter for an explicit property.
|
||||||
uint64_t IsPropertyAccessor : 1;
|
uint64_t IsPropertyAccessor : 1;
|
||||||
|
|
||||||
|
/// True if this method is a synthesized property accessor stub.
|
||||||
|
uint64_t IsSynthesizedAccessorStub : 1;
|
||||||
|
|
||||||
/// Method has a definition.
|
/// Method has a definition.
|
||||||
uint64_t IsDefined : 1;
|
uint64_t IsDefined : 1;
|
||||||
|
|
||||||
|
@ -172,6 +172,7 @@ private:
|
|||||||
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
|
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
|
||||||
DeclContext *contextDecl, bool isInstance = true,
|
DeclContext *contextDecl, bool isInstance = true,
|
||||||
bool isVariadic = false, bool isPropertyAccessor = false,
|
bool isVariadic = false, bool isPropertyAccessor = false,
|
||||||
|
bool isSynthesizedAccessorStub = false,
|
||||||
bool isImplicitlyDeclared = false, bool isDefined = false,
|
bool isImplicitlyDeclared = false, bool isDefined = false,
|
||||||
ImplementationControl impControl = None,
|
ImplementationControl impControl = None,
|
||||||
bool HasRelatedResultType = false);
|
bool HasRelatedResultType = false);
|
||||||
@ -232,6 +233,7 @@ public:
|
|||||||
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
|
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
|
||||||
DeclContext *contextDecl, bool isInstance = true,
|
DeclContext *contextDecl, bool isInstance = true,
|
||||||
bool isVariadic = false, bool isPropertyAccessor = false,
|
bool isVariadic = false, bool isPropertyAccessor = false,
|
||||||
|
bool isSynthesizedAccessorStub = false,
|
||||||
bool isImplicitlyDeclared = false, bool isDefined = false,
|
bool isImplicitlyDeclared = false, bool isDefined = false,
|
||||||
ImplementationControl impControl = None,
|
ImplementationControl impControl = None,
|
||||||
bool HasRelatedResultType = false);
|
bool HasRelatedResultType = false);
|
||||||
@ -436,6 +438,14 @@ public:
|
|||||||
ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
|
ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isSynthesizedAccessorStub() const {
|
||||||
|
return ObjCMethodDeclBits.IsSynthesizedAccessorStub;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSynthesizedAccessorStub(bool isSynthesizedAccessorStub) {
|
||||||
|
ObjCMethodDeclBits.IsSynthesizedAccessorStub = isSynthesizedAccessorStub;
|
||||||
|
}
|
||||||
|
|
||||||
bool isDefined() const { return ObjCMethodDeclBits.IsDefined; }
|
bool isDefined() const { return ObjCMethodDeclBits.IsDefined; }
|
||||||
void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; }
|
void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; }
|
||||||
|
|
||||||
@ -2779,6 +2789,11 @@ private:
|
|||||||
/// Null for \@dynamic. Required for \@synthesize.
|
/// Null for \@dynamic. Required for \@synthesize.
|
||||||
ObjCIvarDecl *PropertyIvarDecl;
|
ObjCIvarDecl *PropertyIvarDecl;
|
||||||
|
|
||||||
|
/// The getter's definition, which has an empty body if synthesized.
|
||||||
|
ObjCMethodDecl *GetterMethodDecl = nullptr;
|
||||||
|
/// The getter's definition, which has an empty body if synthesized.
|
||||||
|
ObjCMethodDecl *SetterMethodDecl = nullptr;
|
||||||
|
|
||||||
/// Null for \@dynamic. Non-null if property must be copy-constructed in
|
/// Null for \@dynamic. Non-null if property must be copy-constructed in
|
||||||
/// getter.
|
/// getter.
|
||||||
Expr *GetterCXXConstructor = nullptr;
|
Expr *GetterCXXConstructor = nullptr;
|
||||||
@ -2845,6 +2860,12 @@ public:
|
|||||||
return IvarLoc.isValid() && IvarLoc != getLocation();
|
return IvarLoc.isValid() && IvarLoc != getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
|
||||||
|
void setGetterMethodDecl(ObjCMethodDecl *MD) { GetterMethodDecl = MD; }
|
||||||
|
|
||||||
|
ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
|
||||||
|
void setSetterMethodDecl(ObjCMethodDecl *MD) { SetterMethodDecl = MD; }
|
||||||
|
|
||||||
Expr *getGetterCXXConstructor() const {
|
Expr *getGetterCXXConstructor() const {
|
||||||
return GetterCXXConstructor;
|
return GetterCXXConstructor;
|
||||||
}
|
}
|
||||||
|
@ -3963,10 +3963,10 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
|||||||
|
|
||||||
ObjCMethodDecl *ToMethod;
|
ObjCMethodDecl *ToMethod;
|
||||||
if (GetImportedOrCreateDecl(
|
if (GetImportedOrCreateDecl(
|
||||||
ToMethod, D, Importer.getToContext(), Loc,
|
ToMethod, D, Importer.getToContext(), Loc, ToEndLoc,
|
||||||
ToEndLoc, Name.getObjCSelector(), ToReturnType,
|
Name.getObjCSelector(), ToReturnType, ToReturnTypeSourceInfo, DC,
|
||||||
ToReturnTypeSourceInfo, DC, D->isInstanceMethod(), D->isVariadic(),
|
D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(),
|
||||||
D->isPropertyAccessor(), D->isImplicit(), D->isDefined(),
|
D->isSynthesizedAccessorStub(), D->isImplicit(), D->isDefined(),
|
||||||
D->getImplementationControl(), D->hasRelatedResultType()))
|
D->getImplementationControl(), D->hasRelatedResultType()))
|
||||||
return ToMethod;
|
return ToMethod;
|
||||||
|
|
||||||
|
@ -775,14 +775,12 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
|
|||||||
// ObjCMethodDecl
|
// ObjCMethodDecl
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
|
ObjCMethodDecl::ObjCMethodDecl(
|
||||||
Selector SelInfo, QualType T,
|
SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo,
|
||||||
TypeSourceInfo *ReturnTInfo,
|
QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl,
|
||||||
DeclContext *contextDecl, bool isInstance,
|
bool isInstance, bool isVariadic, bool isPropertyAccessor,
|
||||||
bool isVariadic, bool isPropertyAccessor,
|
bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined,
|
||||||
bool isImplicitlyDeclared, bool isDefined,
|
ImplementationControl impControl, bool HasRelatedResultType)
|
||||||
ImplementationControl impControl,
|
|
||||||
bool HasRelatedResultType)
|
|
||||||
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
|
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
|
||||||
DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
|
DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
|
||||||
DeclEndLoc(endLoc) {
|
DeclEndLoc(endLoc) {
|
||||||
@ -793,6 +791,7 @@ ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
|
|||||||
setInstanceMethod(isInstance);
|
setInstanceMethod(isInstance);
|
||||||
setVariadic(isVariadic);
|
setVariadic(isVariadic);
|
||||||
setPropertyAccessor(isPropertyAccessor);
|
setPropertyAccessor(isPropertyAccessor);
|
||||||
|
setSynthesizedAccessorStub(isSynthesizedAccessorStub);
|
||||||
setDefined(isDefined);
|
setDefined(isDefined);
|
||||||
setIsRedeclaration(false);
|
setIsRedeclaration(false);
|
||||||
setHasRedeclaration(false);
|
setHasRedeclaration(false);
|
||||||
@ -810,12 +809,13 @@ ObjCMethodDecl *ObjCMethodDecl::Create(
|
|||||||
ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
|
ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
|
||||||
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
|
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
|
||||||
DeclContext *contextDecl, bool isInstance, bool isVariadic,
|
DeclContext *contextDecl, bool isInstance, bool isVariadic,
|
||||||
bool isPropertyAccessor, bool isImplicitlyDeclared, bool isDefined,
|
bool isPropertyAccessor, bool isSynthesizedAccessorStub,
|
||||||
ImplementationControl impControl, bool HasRelatedResultType) {
|
bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl,
|
||||||
|
bool HasRelatedResultType) {
|
||||||
return new (C, contextDecl) ObjCMethodDecl(
|
return new (C, contextDecl) ObjCMethodDecl(
|
||||||
beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance,
|
beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance,
|
||||||
isVariadic, isPropertyAccessor, isImplicitlyDeclared, isDefined,
|
isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
|
||||||
impControl, HasRelatedResultType);
|
isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
||||||
@ -1306,6 +1306,11 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
|
|||||||
|
|
||||||
if (isPropertyAccessor()) {
|
if (isPropertyAccessor()) {
|
||||||
const auto *Container = cast<ObjCContainerDecl>(getParent());
|
const auto *Container = cast<ObjCContainerDecl>(getParent());
|
||||||
|
// For accessor stubs, go back to the interface.
|
||||||
|
if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container))
|
||||||
|
if (isSynthesizedAccessorStub())
|
||||||
|
Container = ImplDecl->getClassInterface();
|
||||||
|
|
||||||
bool IsGetter = (NumArgs == 0);
|
bool IsGetter = (NumArgs == 0);
|
||||||
bool IsInstance = isInstanceMethod();
|
bool IsInstance = isInstanceMethod();
|
||||||
|
|
||||||
@ -1358,6 +1363,15 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(isSynthesizedAccessorStub() && "expected an accessor stub");
|
||||||
|
for (const auto *Cat : ClassDecl->known_categories()) {
|
||||||
|
if (Cat == Container)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (const auto *Found = findMatchingProperty(Cat))
|
||||||
|
return Found;
|
||||||
|
}
|
||||||
|
|
||||||
llvm_unreachable("Marked as a property accessor but no property found!");
|
llvm_unreachable("Marked as a property accessor but no property found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,6 +830,16 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
|
|||||||
if (D->param_size() != 0)
|
if (D->param_size() != 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
// If the property was defined in an extension, search the extensions for
|
||||||
|
// overrides.
|
||||||
|
const ObjCInterfaceDecl *OID = D->getClassInterface();
|
||||||
|
if (dyn_cast<ObjCInterfaceDecl>(D->getParent()) != OID)
|
||||||
|
for (auto *Ext : OID->known_extensions()) {
|
||||||
|
auto *OMD = Ext->getInstanceMethod(D->getSelector());
|
||||||
|
if (OMD && !OMD->isImplicit())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Val = createObjCPropertyGetter(C, Prop);
|
Val = createObjCPropertyGetter(C, Prop);
|
||||||
|
|
||||||
return Val.getValue();
|
return Val.getValue();
|
||||||
|
@ -954,8 +954,7 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
|
|||||||
const ObjCPropertyImplDecl *PID) {
|
const ObjCPropertyImplDecl *PID) {
|
||||||
llvm::Constant *AtomicHelperFn =
|
llvm::Constant *AtomicHelperFn =
|
||||||
CodeGenFunction(CGM).GenerateObjCAtomicGetterCopyHelperFunction(PID);
|
CodeGenFunction(CGM).GenerateObjCAtomicGetterCopyHelperFunction(PID);
|
||||||
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
ObjCMethodDecl *OMD = PID->getGetterMethodDecl();
|
||||||
ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
|
|
||||||
assert(OMD && "Invalid call to generate getter (empty method)");
|
assert(OMD && "Invalid call to generate getter (empty method)");
|
||||||
StartObjCMethod(OMD, IMP->getClassInterface());
|
StartObjCMethod(OMD, IMP->getClassInterface());
|
||||||
|
|
||||||
@ -1041,7 +1040,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
|
|||||||
|
|
||||||
const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
|
const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
|
||||||
QualType propType = prop->getType();
|
QualType propType = prop->getType();
|
||||||
ObjCMethodDecl *getterMethod = prop->getGetterMethodDecl();
|
ObjCMethodDecl *getterMethod = propImpl->getGetterMethodDecl();
|
||||||
|
|
||||||
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
|
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
|
||||||
|
|
||||||
@ -1311,9 +1310,8 @@ void
|
|||||||
CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
|
CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
|
||||||
const ObjCPropertyImplDecl *propImpl,
|
const ObjCPropertyImplDecl *propImpl,
|
||||||
llvm::Constant *AtomicHelperFn) {
|
llvm::Constant *AtomicHelperFn) {
|
||||||
const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
|
|
||||||
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
|
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
|
||||||
ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl();
|
ObjCMethodDecl *setterMethod = propImpl->getSetterMethodDecl();
|
||||||
|
|
||||||
// Just use the setter expression if Sema gave us one and it's
|
// Just use the setter expression if Sema gave us one and it's
|
||||||
// non-trivial.
|
// non-trivial.
|
||||||
@ -1490,8 +1488,7 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
|
|||||||
const ObjCPropertyImplDecl *PID) {
|
const ObjCPropertyImplDecl *PID) {
|
||||||
llvm::Constant *AtomicHelperFn =
|
llvm::Constant *AtomicHelperFn =
|
||||||
CodeGenFunction(CGM).GenerateObjCAtomicSetterCopyHelperFunction(PID);
|
CodeGenFunction(CGM).GenerateObjCAtomicSetterCopyHelperFunction(PID);
|
||||||
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
ObjCMethodDecl *OMD = PID->getSetterMethodDecl();
|
||||||
ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
|
|
||||||
assert(OMD && "Invalid call to generate setter (empty method)");
|
assert(OMD && "Invalid call to generate setter (empty method)");
|
||||||
StartObjCMethod(OMD, IMP->getClassInterface());
|
StartObjCMethod(OMD, IMP->getClassInterface());
|
||||||
|
|
||||||
|
@ -1880,13 +1880,12 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
|
|||||||
for (auto *propImpl : OID->property_impls())
|
for (auto *propImpl : OID->property_impls())
|
||||||
if (propImpl->getPropertyImplementation() ==
|
if (propImpl->getPropertyImplementation() ==
|
||||||
ObjCPropertyImplDecl::Synthesize) {
|
ObjCPropertyImplDecl::Synthesize) {
|
||||||
ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
|
auto addIfExists = [&](const ObjCMethodDecl *OMD) {
|
||||||
auto addIfExists = [&](const ObjCMethodDecl* OMD) {
|
if (OMD && OMD->hasBody())
|
||||||
if (OMD)
|
|
||||||
InstanceMethods.push_back(OMD);
|
InstanceMethods.push_back(OMD);
|
||||||
};
|
};
|
||||||
addIfExists(prop->getGetterMethodDecl());
|
addIfExists(propImpl->getGetterMethodDecl());
|
||||||
addIfExists(prop->getSetterMethodDecl());
|
addIfExists(propImpl->getSetterMethodDecl());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InstanceMethods.size() == 0)
|
if (InstanceMethods.size() == 0)
|
||||||
@ -3494,13 +3493,12 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
|
|||||||
for (auto *propertyImpl : OID->property_impls())
|
for (auto *propertyImpl : OID->property_impls())
|
||||||
if (propertyImpl->getPropertyImplementation() ==
|
if (propertyImpl->getPropertyImplementation() ==
|
||||||
ObjCPropertyImplDecl::Synthesize) {
|
ObjCPropertyImplDecl::Synthesize) {
|
||||||
ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
|
|
||||||
auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
|
auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
|
||||||
if (accessor)
|
if (accessor)
|
||||||
InstanceMethods.push_back(accessor);
|
InstanceMethods.push_back(accessor);
|
||||||
};
|
};
|
||||||
addPropertyMethod(property->getGetterMethodDecl());
|
addPropertyMethod(propertyImpl->getGetterMethodDecl());
|
||||||
addPropertyMethod(property->getSetterMethodDecl());
|
addPropertyMethod(propertyImpl->getSetterMethodDecl());
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
|
llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
|
||||||
|
@ -3559,12 +3559,10 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
|||||||
|
|
||||||
for (const auto *PID : ID->property_impls()) {
|
for (const auto *PID : ID->property_impls()) {
|
||||||
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
|
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
|
||||||
ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
|
||||||
|
|
||||||
if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
|
|
||||||
if (GetMethodDefinition(MD))
|
if (GetMethodDefinition(MD))
|
||||||
Methods[InstanceMethods].push_back(MD);
|
Methods[InstanceMethods].push_back(MD);
|
||||||
if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
|
if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
|
||||||
if (GetMethodDefinition(MD))
|
if (GetMethodDefinition(MD))
|
||||||
Methods[InstanceMethods].push_back(MD);
|
Methods[InstanceMethods].push_back(MD);
|
||||||
}
|
}
|
||||||
@ -6232,19 +6230,6 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
|
|||||||
} else {
|
} else {
|
||||||
for (const auto *MD : ID->instance_methods())
|
for (const auto *MD : ID->instance_methods())
|
||||||
methods.push_back(MD);
|
methods.push_back(MD);
|
||||||
|
|
||||||
for (const auto *PID : ID->property_impls()) {
|
|
||||||
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
|
|
||||||
ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
|
||||||
|
|
||||||
if (auto MD = PD->getGetterMethodDecl())
|
|
||||||
if (GetMethodDefinition(MD))
|
|
||||||
methods.push_back(MD);
|
|
||||||
if (auto MD = PD->getSetterMethodDecl())
|
|
||||||
if (GetMethodDefinition(MD))
|
|
||||||
methods.push_back(MD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
|
values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
|
||||||
@ -6707,9 +6692,8 @@ CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
|
|||||||
// method_count
|
// method_count
|
||||||
values.addInt(ObjCTypes.IntTy, methods.size());
|
values.addInt(ObjCTypes.IntTy, methods.size());
|
||||||
auto methodArray = values.beginArray(ObjCTypes.MethodTy);
|
auto methodArray = values.beginArray(ObjCTypes.MethodTy);
|
||||||
for (auto MD : methods) {
|
for (auto MD : methods)
|
||||||
emitMethodConstant(methodArray, MD, forProtocol);
|
emitMethodConstant(methodArray, MD, forProtocol);
|
||||||
}
|
|
||||||
methodArray.finishAndAddTo(values);
|
methodArray.finishAndAddTo(values);
|
||||||
|
|
||||||
llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
|
llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
|
||||||
|
@ -690,8 +690,7 @@ static llvm::Constant *getPrologueSignature(CodeGenModule &CGM,
|
|||||||
return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM);
|
return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::StartFunction(GlobalDecl GD,
|
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
|
||||||
QualType RetTy,
|
|
||||||
llvm::Function *Fn,
|
llvm::Function *Fn,
|
||||||
const CGFunctionInfo &FnInfo,
|
const CGFunctionInfo &FnInfo,
|
||||||
const FunctionArgList &Args,
|
const FunctionArgList &Args,
|
||||||
|
@ -5113,11 +5113,12 @@ void CodeGenModule::EmitObjCPropertyImplementations(const
|
|||||||
// we want, that just indicates if the decl came from a
|
// we want, that just indicates if the decl came from a
|
||||||
// property. What we want to know is if the method is defined in
|
// property. What we want to know is if the method is defined in
|
||||||
// this implementation.
|
// this implementation.
|
||||||
if (!D->getInstanceMethod(PD->getGetterName()))
|
auto *Getter = PID->getGetterMethodDecl();
|
||||||
|
if (!Getter || Getter->isSynthesizedAccessorStub())
|
||||||
CodeGenFunction(*this).GenerateObjCGetter(
|
CodeGenFunction(*this).GenerateObjCGetter(
|
||||||
const_cast<ObjCImplementationDecl *>(D), PID);
|
const_cast<ObjCImplementationDecl *>(D), PID);
|
||||||
if (!PD->isReadOnly() &&
|
auto *Setter = PID->getSetterMethodDecl();
|
||||||
!D->getInstanceMethod(PD->getSetterName()))
|
if (!PD->isReadOnly() && (!Setter || Setter->isSynthesizedAccessorStub()))
|
||||||
CodeGenFunction(*this).GenerateObjCSetter(
|
CodeGenFunction(*this).GenerateObjCSetter(
|
||||||
const_cast<ObjCImplementationDecl *>(D), PID);
|
const_cast<ObjCImplementationDecl *>(D), PID);
|
||||||
}
|
}
|
||||||
@ -5154,12 +5155,13 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
|
|||||||
if (needsDestructMethod(D)) {
|
if (needsDestructMethod(D)) {
|
||||||
IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct");
|
IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct");
|
||||||
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
|
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
|
||||||
ObjCMethodDecl *DTORMethod =
|
ObjCMethodDecl *DTORMethod = ObjCMethodDecl::Create(
|
||||||
ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(),
|
getContext(), D->getLocation(), D->getLocation(), cxxSelector,
|
||||||
cxxSelector, getContext().VoidTy, nullptr, D,
|
getContext().VoidTy, nullptr, D,
|
||||||
/*isInstance=*/true, /*isVariadic=*/false,
|
/*isInstance=*/true, /*isVariadic=*/false,
|
||||||
/*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true,
|
/*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
|
||||||
/*isDefined=*/false, ObjCMethodDecl::Required);
|
/*isImplicitlyDeclared=*/true,
|
||||||
|
/*isDefined=*/false, ObjCMethodDecl::Required);
|
||||||
D->addInstanceMethod(DTORMethod);
|
D->addInstanceMethod(DTORMethod);
|
||||||
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
|
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
|
||||||
D->setHasDestructors(true);
|
D->setHasDestructors(true);
|
||||||
@ -5174,17 +5176,13 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
|
|||||||
IdentifierInfo *II = &getContext().Idents.get(".cxx_construct");
|
IdentifierInfo *II = &getContext().Idents.get(".cxx_construct");
|
||||||
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
|
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
|
||||||
// The constructor returns 'self'.
|
// The constructor returns 'self'.
|
||||||
ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(),
|
ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(
|
||||||
D->getLocation(),
|
getContext(), D->getLocation(), D->getLocation(), cxxSelector,
|
||||||
D->getLocation(),
|
getContext().getObjCIdType(), nullptr, D, /*isInstance=*/true,
|
||||||
cxxSelector,
|
/*isVariadic=*/false,
|
||||||
getContext().getObjCIdType(),
|
/*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
|
||||||
nullptr, D, /*isInstance=*/true,
|
/*isImplicitlyDeclared=*/true,
|
||||||
/*isVariadic=*/false,
|
/*isDefined=*/false, ObjCMethodDecl::Required);
|
||||||
/*isPropertyAccessor=*/true,
|
|
||||||
/*isImplicitlyDeclared=*/true,
|
|
||||||
/*isDefined=*/false,
|
|
||||||
ObjCMethodDecl::Required);
|
|
||||||
D->addInstanceMethod(CTORMethod);
|
D->addInstanceMethod(CTORMethod);
|
||||||
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
|
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
|
||||||
D->setHasNonZeroConstructors(true);
|
D->setHasNonZeroConstructors(true);
|
||||||
|
@ -908,9 +908,9 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
|
|||||||
static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,
|
static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,
|
||||||
ObjCPropertyDecl *PD,
|
ObjCPropertyDecl *PD,
|
||||||
bool getter) {
|
bool getter) {
|
||||||
return getter ? !IMP->getInstanceMethod(PD->getGetterName())
|
auto *OMD = IMP->getInstanceMethod(getter ? PD->getGetterName()
|
||||||
: !IMP->getInstanceMethod(PD->getSetterName());
|
: PD->getSetterName());
|
||||||
|
return !OMD || OMD->isSynthesizedAccessorStub();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
||||||
@ -952,7 +952,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|||||||
"id objc_getProperty(id, SEL, long, bool);\n";
|
"id objc_getProperty(id, SEL, long, bool);\n";
|
||||||
}
|
}
|
||||||
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
||||||
PD->getGetterMethodDecl(), Getr);
|
PID->getGetterMethodDecl(), Getr);
|
||||||
Getr += "{ ";
|
Getr += "{ ";
|
||||||
// Synthesize an explicit cast to gain access to the ivar.
|
// Synthesize an explicit cast to gain access to the ivar.
|
||||||
// See objc-act.c:objc_synthesize_new_getter() for details.
|
// See objc-act.c:objc_synthesize_new_getter() for details.
|
||||||
@ -960,7 +960,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|||||||
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
|
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
|
||||||
Getr += "typedef ";
|
Getr += "typedef ";
|
||||||
const FunctionType *FPRetType = nullptr;
|
const FunctionType *FPRetType = nullptr;
|
||||||
RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr,
|
RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,
|
||||||
FPRetType);
|
FPRetType);
|
||||||
Getr += " _TYPE";
|
Getr += " _TYPE";
|
||||||
if (FPRetType) {
|
if (FPRetType) {
|
||||||
@ -1012,7 +1012,7 @@ void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|||||||
}
|
}
|
||||||
|
|
||||||
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
||||||
PD->getSetterMethodDecl(), Setr);
|
PID->getSetterMethodDecl(), Setr);
|
||||||
Setr += "{ ";
|
Setr += "{ ";
|
||||||
// Synthesize an explicit cast to initialize the ivar.
|
// Synthesize an explicit cast to initialize the ivar.
|
||||||
// See objc-act.c:objc_synthesize_new_setter() for details.
|
// See objc-act.c:objc_synthesize_new_setter() for details.
|
||||||
@ -1346,6 +1346,8 @@ void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
|
|||||||
InsertText(CID->getBeginLoc(), "// ");
|
InsertText(CID->getBeginLoc(), "// ");
|
||||||
|
|
||||||
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
|
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
|
||||||
|
if (!OMD->getBody())
|
||||||
|
continue;
|
||||||
std::string ResultStr;
|
std::string ResultStr;
|
||||||
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
||||||
SourceLocation LocStart = OMD->getBeginLoc();
|
SourceLocation LocStart = OMD->getBeginLoc();
|
||||||
@ -1357,6 +1359,8 @@ void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
|
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
|
||||||
|
if (!OMD->getBody())
|
||||||
|
continue;
|
||||||
std::string ResultStr;
|
std::string ResultStr;
|
||||||
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
||||||
SourceLocation LocStart = OMD->getBeginLoc();
|
SourceLocation LocStart = OMD->getBeginLoc();
|
||||||
@ -7031,12 +7035,12 @@ void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
|
|||||||
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
|
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
|
||||||
if (!PD)
|
if (!PD)
|
||||||
continue;
|
continue;
|
||||||
if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
|
if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
|
||||||
if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))
|
if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))
|
||||||
InstanceMethods.push_back(Getter);
|
InstanceMethods.push_back(Getter);
|
||||||
if (PD->isReadOnly())
|
if (PD->isReadOnly())
|
||||||
continue;
|
continue;
|
||||||
if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
|
if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
|
||||||
if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))
|
if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))
|
||||||
InstanceMethods.push_back(Setter);
|
InstanceMethods.push_back(Setter);
|
||||||
}
|
}
|
||||||
@ -7281,11 +7285,11 @@ void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
|
|||||||
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
|
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
|
||||||
if (!PD)
|
if (!PD)
|
||||||
continue;
|
continue;
|
||||||
if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
|
if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
|
||||||
InstanceMethods.push_back(Getter);
|
InstanceMethods.push_back(Getter);
|
||||||
if (PD->isReadOnly())
|
if (PD->isReadOnly())
|
||||||
continue;
|
continue;
|
||||||
if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
|
if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
|
||||||
InstanceMethods.push_back(Setter);
|
InstanceMethods.push_back(Setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,8 +786,9 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|||||||
|
|
||||||
if (!OID)
|
if (!OID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned Attributes = PD->getPropertyAttributes();
|
unsigned Attributes = PD->getPropertyAttributes();
|
||||||
if (!PD->getGetterMethodDecl()->isDefined()) {
|
if (PID->getGetterMethodDecl() && !PID->getGetterMethodDecl()->isDefined()) {
|
||||||
bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
|
bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
|
||||||
(Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
|
(Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
|
||||||
ObjCPropertyDecl::OBJC_PR_copy));
|
ObjCPropertyDecl::OBJC_PR_copy));
|
||||||
@ -799,7 +800,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|||||||
"id objc_getProperty(id, SEL, long, bool);\n";
|
"id objc_getProperty(id, SEL, long, bool);\n";
|
||||||
}
|
}
|
||||||
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
||||||
PD->getGetterMethodDecl(), Getr);
|
PID->getGetterMethodDecl(), Getr);
|
||||||
Getr += "{ ";
|
Getr += "{ ";
|
||||||
// Synthesize an explicit cast to gain access to the ivar.
|
// Synthesize an explicit cast to gain access to the ivar.
|
||||||
// See objc-act.c:objc_synthesize_new_getter() for details.
|
// See objc-act.c:objc_synthesize_new_getter() for details.
|
||||||
@ -807,7 +808,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|||||||
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
|
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
|
||||||
Getr += "typedef ";
|
Getr += "typedef ";
|
||||||
const FunctionType *FPRetType = nullptr;
|
const FunctionType *FPRetType = nullptr;
|
||||||
RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr,
|
RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,
|
||||||
FPRetType);
|
FPRetType);
|
||||||
Getr += " _TYPE";
|
Getr += " _TYPE";
|
||||||
if (FPRetType) {
|
if (FPRetType) {
|
||||||
@ -843,7 +844,8 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|||||||
InsertText(onePastSemiLoc, Getr);
|
InsertText(onePastSemiLoc, Getr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined())
|
if (PD->isReadOnly() || !PID->getSetterMethodDecl() ||
|
||||||
|
PID->getSetterMethodDecl()->isDefined())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Generate the 'setter' function.
|
// Generate the 'setter' function.
|
||||||
@ -858,7 +860,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
|
|||||||
}
|
}
|
||||||
|
|
||||||
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
RewriteObjCMethodDecl(OID->getContainingInterface(),
|
||||||
PD->getSetterMethodDecl(), Setr);
|
PID->getSetterMethodDecl(), Setr);
|
||||||
Setr += "{ ";
|
Setr += "{ ";
|
||||||
// Synthesize an explicit cast to initialize the ivar.
|
// Synthesize an explicit cast to initialize the ivar.
|
||||||
// See objc-act.c:objc_synthesize_new_setter() for details.
|
// See objc-act.c:objc_synthesize_new_setter() for details.
|
||||||
@ -1168,6 +1170,8 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
|
|||||||
InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// ");
|
InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// ");
|
||||||
|
|
||||||
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
|
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
|
||||||
|
if (!OMD->getBody())
|
||||||
|
continue;
|
||||||
std::string ResultStr;
|
std::string ResultStr;
|
||||||
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
||||||
SourceLocation LocStart = OMD->getBeginLoc();
|
SourceLocation LocStart = OMD->getBeginLoc();
|
||||||
@ -1179,6 +1183,8 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
|
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
|
||||||
|
if (!OMD->getBody())
|
||||||
|
continue;
|
||||||
std::string ResultStr;
|
std::string ResultStr;
|
||||||
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
|
||||||
SourceLocation LocStart = OMD->getBeginLoc();
|
SourceLocation LocStart = OMD->getBeginLoc();
|
||||||
@ -5355,12 +5361,12 @@ void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDe
|
|||||||
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
|
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
|
||||||
if (!PD)
|
if (!PD)
|
||||||
continue;
|
continue;
|
||||||
if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
|
if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
|
||||||
if (!Getter->isDefined())
|
if (!Getter->isDefined())
|
||||||
InstanceMethods.push_back(Getter);
|
InstanceMethods.push_back(Getter);
|
||||||
if (PD->isReadOnly())
|
if (PD->isReadOnly())
|
||||||
continue;
|
continue;
|
||||||
if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
|
if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
|
||||||
if (!Setter->isDefined())
|
if (!Setter->isDefined())
|
||||||
InstanceMethods.push_back(Setter);
|
InstanceMethods.push_back(Setter);
|
||||||
}
|
}
|
||||||
@ -5633,11 +5639,11 @@ void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *ID
|
|||||||
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
|
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
|
||||||
if (!PD)
|
if (!PD)
|
||||||
continue;
|
continue;
|
||||||
if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
|
if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
|
||||||
InstanceMethods.push_back(Getter);
|
InstanceMethods.push_back(Getter);
|
||||||
if (PD->isReadOnly())
|
if (PD->isReadOnly())
|
||||||
continue;
|
continue;
|
||||||
if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
|
if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
|
||||||
InstanceMethods.push_back(Setter);
|
InstanceMethods.push_back(Setter);
|
||||||
}
|
}
|
||||||
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
|
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
|
||||||
|
@ -42,15 +42,6 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the given method has been defined explicitly by the
|
|
||||||
/// user.
|
|
||||||
static bool hasUserDefined(const ObjCMethodDecl *D,
|
|
||||||
const ObjCImplDecl *Container) {
|
|
||||||
const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
|
|
||||||
D->isInstanceMethod());
|
|
||||||
return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
|
void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
|
||||||
const NamedDecl *Parent,
|
const NamedDecl *Parent,
|
||||||
const DeclContext *DC) {
|
const DeclContext *DC) {
|
||||||
@ -78,6 +69,17 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the given method has been defined explicitly by the
|
||||||
|
/// user.
|
||||||
|
static bool hasUserDefined(const ObjCMethodDecl *D,
|
||||||
|
const ObjCImplDecl *Container) {
|
||||||
|
const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
|
||||||
|
D->isInstanceMethod());
|
||||||
|
return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition() &&
|
||||||
|
!MD->isSynthesizedAccessorStub();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void handleDeclarator(const DeclaratorDecl *D,
|
void handleDeclarator(const DeclaratorDecl *D,
|
||||||
const NamedDecl *Parent = nullptr,
|
const NamedDecl *Parent = nullptr,
|
||||||
bool isIBType = false) {
|
bool isIBType = false) {
|
||||||
@ -534,13 +536,11 @@ public:
|
|||||||
SymbolRoleSet AccessorMethodRoles =
|
SymbolRoleSet AccessorMethodRoles =
|
||||||
SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
|
SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
|
||||||
if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
|
if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
|
||||||
if (MD->isPropertyAccessor() &&
|
if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
|
||||||
!hasUserDefined(MD, Container))
|
|
||||||
IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
|
IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
|
||||||
}
|
}
|
||||||
if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
|
if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
|
||||||
if (MD->isPropertyAccessor() &&
|
if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
|
||||||
!hasUserDefined(MD, Container))
|
|
||||||
IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
|
IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
|
||||||
}
|
}
|
||||||
if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
|
if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
|
||||||
|
@ -2828,6 +2828,9 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
|
|||||||
"Expected to find the method through lookup as well");
|
"Expected to find the method through lookup as well");
|
||||||
// ImpMethodDecl may be null as in a @dynamic property.
|
// ImpMethodDecl may be null as in a @dynamic property.
|
||||||
if (ImpMethodDecl) {
|
if (ImpMethodDecl) {
|
||||||
|
// Skip property accessor function stubs.
|
||||||
|
if (ImpMethodDecl->isSynthesizedAccessorStub())
|
||||||
|
continue;
|
||||||
if (!WarnCategoryMethodImpl)
|
if (!WarnCategoryMethodImpl)
|
||||||
WarnConflictingTypedMethods(ImpMethodDecl, I,
|
WarnConflictingTypedMethods(ImpMethodDecl, I,
|
||||||
isa<ObjCProtocolDecl>(CDecl));
|
isa<ObjCProtocolDecl>(CDecl));
|
||||||
@ -2854,6 +2857,9 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap,
|
|||||||
"Expected to find the method through lookup as well");
|
"Expected to find the method through lookup as well");
|
||||||
// ImpMethodDecl may be null as in a @dynamic property.
|
// ImpMethodDecl may be null as in a @dynamic property.
|
||||||
if (ImpMethodDecl) {
|
if (ImpMethodDecl) {
|
||||||
|
// Skip property accessor function stubs.
|
||||||
|
if (ImpMethodDecl->isSynthesizedAccessorStub())
|
||||||
|
continue;
|
||||||
if (!WarnCategoryMethodImpl)
|
if (!WarnCategoryMethodImpl)
|
||||||
WarnConflictingTypedMethods(ImpMethodDecl, I,
|
WarnConflictingTypedMethods(ImpMethodDecl, I,
|
||||||
isa<ObjCProtocolDecl>(CDecl));
|
isa<ObjCProtocolDecl>(CDecl));
|
||||||
@ -3903,6 +3909,25 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
|
|||||||
|| isa<ObjCProtocolDecl>(ClassDecl);
|
|| isa<ObjCProtocolDecl>(ClassDecl);
|
||||||
bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);
|
bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);
|
||||||
|
|
||||||
|
// Make synthesized accessor stub functions visible.
|
||||||
|
// ActOnPropertyImplDecl() creates them as not visible in case
|
||||||
|
// they are overridden by an explicit method that is encountered
|
||||||
|
// later.
|
||||||
|
if (auto *OID = dyn_cast<ObjCImplementationDecl>(CurContext)) {
|
||||||
|
for (auto PropImpl : OID->property_impls()) {
|
||||||
|
if (auto *Getter = PropImpl->getGetterMethodDecl())
|
||||||
|
if (Getter->isSynthesizedAccessorStub()) {
|
||||||
|
OID->makeDeclVisibleInContext(Getter);
|
||||||
|
OID->addDecl(Getter);
|
||||||
|
}
|
||||||
|
if (auto *Setter = PropImpl->getSetterMethodDecl())
|
||||||
|
if (Setter->isSynthesizedAccessorStub()) {
|
||||||
|
OID->makeDeclVisibleInContext(Setter);
|
||||||
|
OID->addDecl(Setter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
|
// FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
|
||||||
llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
|
llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
|
||||||
llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
|
llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
|
||||||
@ -4001,8 +4026,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (const auto *Ext : IDecl->visible_extensions()) {
|
for (const auto *Ext : IDecl->visible_extensions()) {
|
||||||
if (ObjCMethodDecl *GetterMethod
|
if (ObjCMethodDecl *GetterMethod =
|
||||||
= Ext->getInstanceMethod(Property->getGetterName()))
|
Ext->getInstanceMethod(Property->getGetterName()))
|
||||||
GetterMethod->setPropertyAccessor(true);
|
GetterMethod->setPropertyAccessor(true);
|
||||||
if (!Property->isReadOnly())
|
if (!Property->isReadOnly())
|
||||||
if (ObjCMethodDecl *SetterMethod
|
if (ObjCMethodDecl *SetterMethod
|
||||||
@ -4551,6 +4576,7 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||||||
Diag(MethodLoc, diag::err_missing_method_context);
|
Diag(MethodLoc, diag::err_missing_method_context);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Decl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
|
Decl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
|
||||||
QualType resultDeclType;
|
QualType resultDeclType;
|
||||||
|
|
||||||
@ -4574,7 +4600,7 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||||||
ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create(
|
ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create(
|
||||||
Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, CurContext,
|
Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, CurContext,
|
||||||
MethodType == tok::minus, isVariadic,
|
MethodType == tok::minus, isVariadic,
|
||||||
/*isPropertyAccessor=*/false,
|
/*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,
|
||||||
/*isImplicitlyDeclared=*/false, /*isDefined=*/false,
|
/*isImplicitlyDeclared=*/false, /*isDefined=*/false,
|
||||||
MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional
|
MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional
|
||||||
: ObjCMethodDecl::Required,
|
: ObjCMethodDecl::Required,
|
||||||
@ -4666,6 +4692,27 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||||||
ImpDecl->addClassMethod(ObjCMethod);
|
ImpDecl->addClassMethod(ObjCMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this method overrides a previous @synthesize declaration,
|
||||||
|
// register it with the property. Linear search through all
|
||||||
|
// properties here, because the autosynthesized stub hasn't been
|
||||||
|
// made visible yet, so it can be overriden by a later
|
||||||
|
// user-specified implementation.
|
||||||
|
for (ObjCPropertyImplDecl *PropertyImpl : ImpDecl->property_impls()) {
|
||||||
|
if (auto *Setter = PropertyImpl->getSetterMethodDecl())
|
||||||
|
if (Setter->getSelector() == Sel &&
|
||||||
|
Setter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) {
|
||||||
|
assert(Setter->isSynthesizedAccessorStub() && "autosynth stub expected");
|
||||||
|
PropertyImpl->setSetterMethodDecl(ObjCMethod);
|
||||||
|
}
|
||||||
|
if (auto *Getter = PropertyImpl->getGetterMethodDecl())
|
||||||
|
if (Getter->getSelector() == Sel &&
|
||||||
|
Getter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) {
|
||||||
|
assert(Getter->isSynthesizedAccessorStub() && "autosynth stub expected");
|
||||||
|
PropertyImpl->setGetterMethodDecl(ObjCMethod);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Merge information from the @interface declaration into the
|
// Merge information from the @interface declaration into the
|
||||||
// @implementation.
|
// @implementation.
|
||||||
if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) {
|
if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) {
|
||||||
@ -5063,6 +5110,9 @@ void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S,
|
|||||||
if (!IV)
|
if (!IV)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (CurMethod->isSynthesizedAccessorStub())
|
||||||
|
continue;
|
||||||
|
|
||||||
UnusedBackingIvarChecker Checker(*this, CurMethod, IV);
|
UnusedBackingIvarChecker Checker(*this, CurMethod, IV);
|
||||||
Checker.TraverseStmt(CurMethod->getBody());
|
Checker.TraverseStmt(CurMethod->getBody());
|
||||||
if (Checker.AccessedIvar)
|
if (Checker.AccessedIvar)
|
||||||
|
@ -288,6 +288,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc,
|
|||||||
S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl,
|
S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl,
|
||||||
/*isInstance=*/false, /*isVariadic=*/false,
|
/*isInstance=*/false, /*isVariadic=*/false,
|
||||||
/*isPropertyAccessor=*/false,
|
/*isPropertyAccessor=*/false,
|
||||||
|
/*isSynthesizedAccessorStub=*/false,
|
||||||
/*isImplicitlyDeclared=*/true,
|
/*isImplicitlyDeclared=*/true,
|
||||||
/*isDefined=*/false, ObjCMethodDecl::Required,
|
/*isDefined=*/false, ObjCMethodDecl::Required,
|
||||||
/*HasRelatedResultType=*/false);
|
/*HasRelatedResultType=*/false);
|
||||||
@ -563,6 +564,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||||||
NSStringPointer, ReturnTInfo, NSStringDecl,
|
NSStringPointer, ReturnTInfo, NSStringDecl,
|
||||||
/*isInstance=*/false, /*isVariadic=*/false,
|
/*isInstance=*/false, /*isVariadic=*/false,
|
||||||
/*isPropertyAccessor=*/false,
|
/*isPropertyAccessor=*/false,
|
||||||
|
/*isSynthesizedAccessorStub=*/false,
|
||||||
/*isImplicitlyDeclared=*/true,
|
/*isImplicitlyDeclared=*/true,
|
||||||
/*isDefined=*/false, ObjCMethodDecl::Required,
|
/*isDefined=*/false, ObjCMethodDecl::Required,
|
||||||
/*HasRelatedResultType=*/false);
|
/*HasRelatedResultType=*/false);
|
||||||
@ -671,20 +673,15 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
|
|||||||
// Debugger needs to work even if NSValue hasn't been defined.
|
// Debugger needs to work even if NSValue hasn't been defined.
|
||||||
TypeSourceInfo *ReturnTInfo = nullptr;
|
TypeSourceInfo *ReturnTInfo = nullptr;
|
||||||
ObjCMethodDecl *M = ObjCMethodDecl::Create(
|
ObjCMethodDecl *M = ObjCMethodDecl::Create(
|
||||||
Context,
|
Context, SourceLocation(), SourceLocation(), ValueWithBytesObjCType,
|
||||||
SourceLocation(),
|
NSValuePointer, ReturnTInfo, NSValueDecl,
|
||||||
SourceLocation(),
|
/*isInstance=*/false,
|
||||||
ValueWithBytesObjCType,
|
/*isVariadic=*/false,
|
||||||
NSValuePointer,
|
/*isPropertyAccessor=*/false,
|
||||||
ReturnTInfo,
|
/*isSynthesizedAccessorStub=*/false,
|
||||||
NSValueDecl,
|
/*isImplicitlyDeclared=*/true,
|
||||||
/*isInstance=*/false,
|
/*isDefined=*/false, ObjCMethodDecl::Required,
|
||||||
/*isVariadic=*/false,
|
/*HasRelatedResultType=*/false);
|
||||||
/*isPropertyAccessor=*/false,
|
|
||||||
/*isImplicitlyDeclared=*/true,
|
|
||||||
/*isDefined=*/false,
|
|
||||||
ObjCMethodDecl::Required,
|
|
||||||
/*HasRelatedResultType=*/false);
|
|
||||||
|
|
||||||
SmallVector<ParmVarDecl *, 2> Params;
|
SmallVector<ParmVarDecl *, 2> Params;
|
||||||
|
|
||||||
@ -815,7 +812,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
|
|||||||
Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,
|
Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,
|
||||||
Context.getTranslationUnitDecl(), false /*Instance*/,
|
Context.getTranslationUnitDecl(), false /*Instance*/,
|
||||||
false /*isVariadic*/,
|
false /*isVariadic*/,
|
||||||
/*isPropertyAccessor=*/false,
|
/*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,
|
||||||
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
||||||
ObjCMethodDecl::Required, false);
|
ObjCMethodDecl::Required, false);
|
||||||
SmallVector<ParmVarDecl *, 2> Params;
|
SmallVector<ParmVarDecl *, 2> Params;
|
||||||
@ -916,16 +913,14 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR,
|
|||||||
NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
|
NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
|
||||||
ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);
|
ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);
|
||||||
if (!Method && getLangOpts().DebuggerObjCLiteral) {
|
if (!Method && getLangOpts().DebuggerObjCLiteral) {
|
||||||
Method = ObjCMethodDecl::Create(Context,
|
Method = ObjCMethodDecl::Create(
|
||||||
SourceLocation(), SourceLocation(), Sel,
|
Context, SourceLocation(), SourceLocation(), Sel, IdT,
|
||||||
IdT,
|
nullptr /*TypeSourceInfo */, Context.getTranslationUnitDecl(),
|
||||||
nullptr /*TypeSourceInfo */,
|
false /*Instance*/, false /*isVariadic*/,
|
||||||
Context.getTranslationUnitDecl(),
|
/*isPropertyAccessor=*/false,
|
||||||
false /*Instance*/, false/*isVariadic*/,
|
/*isSynthesizedAccessorStub=*/false,
|
||||||
/*isPropertyAccessor=*/false,
|
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
||||||
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
ObjCMethodDecl::Required, false);
|
||||||
ObjCMethodDecl::Required,
|
|
||||||
false);
|
|
||||||
SmallVector<ParmVarDecl *, 3> Params;
|
SmallVector<ParmVarDecl *, 3> Params;
|
||||||
ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
|
ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
|
||||||
SourceLocation(),
|
SourceLocation(),
|
||||||
|
@ -1037,6 +1037,31 @@ static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a synthesized property accessor stub inside the \@implementation.
|
||||||
|
static ObjCMethodDecl *
|
||||||
|
RedeclarePropertyAccessor(ASTContext &Context, ObjCImplementationDecl *Impl,
|
||||||
|
ObjCMethodDecl *AccessorDecl, SourceLocation AtLoc,
|
||||||
|
SourceLocation PropertyLoc) {
|
||||||
|
ObjCMethodDecl *Decl = AccessorDecl;
|
||||||
|
ObjCMethodDecl *ImplDecl = ObjCMethodDecl::Create(
|
||||||
|
Context, AtLoc, PropertyLoc, Decl->getSelector(), Decl->getReturnType(),
|
||||||
|
Decl->getReturnTypeSourceInfo(), Impl, Decl->isInstanceMethod(),
|
||||||
|
Decl->isVariadic(), Decl->isPropertyAccessor(), /* isSynthesized*/ true,
|
||||||
|
Decl->isImplicit(), Decl->isDefined(), Decl->getImplementationControl(),
|
||||||
|
Decl->hasRelatedResultType());
|
||||||
|
ImplDecl->getMethodFamily();
|
||||||
|
if (Decl->hasAttrs())
|
||||||
|
ImplDecl->setAttrs(Decl->getAttrs());
|
||||||
|
ImplDecl->setSelfDecl(Decl->getSelfDecl());
|
||||||
|
ImplDecl->setCmdDecl(Decl->getCmdDecl());
|
||||||
|
SmallVector<SourceLocation, 1> SelLocs;
|
||||||
|
Decl->getSelectorLocs(SelLocs);
|
||||||
|
ImplDecl->setMethodParams(Context, Decl->parameters(), SelLocs);
|
||||||
|
ImplDecl->setLexicalDeclContext(Impl);
|
||||||
|
ImplDecl->setDefined(false);
|
||||||
|
return ImplDecl;
|
||||||
|
}
|
||||||
|
|
||||||
/// ActOnPropertyImplDecl - This routine performs semantic checks and
|
/// ActOnPropertyImplDecl - This routine performs semantic checks and
|
||||||
/// builds the AST node for a property implementation declaration; declared
|
/// builds the AST node for a property implementation declaration; declared
|
||||||
/// as \@synthesize or \@dynamic.
|
/// as \@synthesize or \@dynamic.
|
||||||
@ -1404,6 +1429,18 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||||||
|
|
||||||
if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
|
if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
|
||||||
getterMethod->createImplicitParams(Context, IDecl);
|
getterMethod->createImplicitParams(Context, IDecl);
|
||||||
|
|
||||||
|
// Redeclare the getter within the implementation as DeclContext.
|
||||||
|
if (Synthesize) {
|
||||||
|
// If the method hasn't been overridden, create a synthesized implementation.
|
||||||
|
ObjCMethodDecl *OMD = ClassImpDecl->getMethod(
|
||||||
|
getterMethod->getSelector(), getterMethod->isInstanceMethod());
|
||||||
|
if (!OMD)
|
||||||
|
OMD = RedeclarePropertyAccessor(Context, IC, getterMethod, AtLoc,
|
||||||
|
PropertyLoc);
|
||||||
|
PIDecl->setGetterMethodDecl(OMD);
|
||||||
|
}
|
||||||
|
|
||||||
if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
|
if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
|
||||||
Ivar->getType()->isRecordType()) {
|
Ivar->getType()->isRecordType()) {
|
||||||
// For Objective-C++, need to synthesize the AST for the IVAR object to be
|
// For Objective-C++, need to synthesize the AST for the IVAR object to be
|
||||||
@ -1456,8 +1493,20 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
|
if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
|
||||||
setterMethod->createImplicitParams(Context, IDecl);
|
setterMethod->createImplicitParams(Context, IDecl);
|
||||||
|
|
||||||
|
// Redeclare the setter within the implementation as DeclContext.
|
||||||
|
if (Synthesize) {
|
||||||
|
ObjCMethodDecl *OMD = ClassImpDecl->getMethod(
|
||||||
|
setterMethod->getSelector(), setterMethod->isInstanceMethod());
|
||||||
|
if (!OMD)
|
||||||
|
OMD = RedeclarePropertyAccessor(Context, IC, setterMethod,
|
||||||
|
AtLoc, PropertyLoc);
|
||||||
|
PIDecl->setSetterMethodDecl(OMD);
|
||||||
|
}
|
||||||
|
|
||||||
if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
|
if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
|
||||||
Ivar->getType()->isRecordType()) {
|
Ivar->getType()->isRecordType()) {
|
||||||
// FIXME. Eventually we want to do this for Objective-C as well.
|
// FIXME. Eventually we want to do this for Objective-C as well.
|
||||||
@ -1852,10 +1901,12 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
|
|||||||
if (IMPDecl->FindPropertyImplDecl(
|
if (IMPDecl->FindPropertyImplDecl(
|
||||||
Prop->getIdentifier(), Prop->getQueryKind()))
|
Prop->getIdentifier(), Prop->getQueryKind()))
|
||||||
continue;
|
continue;
|
||||||
if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
|
ObjCMethodDecl *ImpMethod = IMPDecl->getInstanceMethod(Prop->getGetterName());
|
||||||
|
if (ImpMethod && !ImpMethod->getBody()) {
|
||||||
if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
|
if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
|
||||||
continue;
|
continue;
|
||||||
if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
|
ImpMethod = IMPDecl->getInstanceMethod(Prop->getSetterName());
|
||||||
|
if (ImpMethod && !ImpMethod->getBody())
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ObjCPropertyImplDecl *PID =
|
if (ObjCPropertyImplDecl *PID =
|
||||||
@ -2083,7 +2134,6 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
|
|||||||
void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) {
|
void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) {
|
||||||
for (const auto *propertyImpl : impDecl->property_impls()) {
|
for (const auto *propertyImpl : impDecl->property_impls()) {
|
||||||
const auto *property = propertyImpl->getPropertyDecl();
|
const auto *property = propertyImpl->getPropertyDecl();
|
||||||
|
|
||||||
// Warn about null_resettable properties with synthesized setters,
|
// Warn about null_resettable properties with synthesized setters,
|
||||||
// because the setter won't properly handle nil.
|
// because the setter won't properly handle nil.
|
||||||
if (propertyImpl->getPropertyImplementation()
|
if (propertyImpl->getPropertyImplementation()
|
||||||
@ -2092,16 +2142,16 @@ void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl)
|
|||||||
ObjCPropertyDecl::OBJC_PR_null_resettable) &&
|
ObjCPropertyDecl::OBJC_PR_null_resettable) &&
|
||||||
property->getGetterMethodDecl() &&
|
property->getGetterMethodDecl() &&
|
||||||
property->getSetterMethodDecl()) {
|
property->getSetterMethodDecl()) {
|
||||||
auto *getterMethod = property->getGetterMethodDecl();
|
auto *getterImpl = propertyImpl->getGetterMethodDecl();
|
||||||
auto *setterMethod = property->getSetterMethodDecl();
|
auto *setterImpl = propertyImpl->getSetterMethodDecl();
|
||||||
if (!impDecl->getInstanceMethod(setterMethod->getSelector()) &&
|
if ((!getterImpl || getterImpl->isSynthesizedAccessorStub()) &&
|
||||||
!impDecl->getInstanceMethod(getterMethod->getSelector())) {
|
(!setterImpl || setterImpl->isSynthesizedAccessorStub())) {
|
||||||
SourceLocation loc = propertyImpl->getLocation();
|
SourceLocation loc = propertyImpl->getLocation();
|
||||||
if (loc.isInvalid())
|
if (loc.isInvalid())
|
||||||
loc = impDecl->getBeginLoc();
|
loc = impDecl->getBeginLoc();
|
||||||
|
|
||||||
Diag(loc, diag::warn_null_resettable_setter)
|
Diag(loc, diag::warn_null_resettable_setter)
|
||||||
<< setterMethod->getSelector() << property->getDeclName();
|
<< setterImpl->getSelector() << property->getDeclName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2138,6 +2188,10 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
|
|||||||
SetterMethod = Property->isClassProperty() ?
|
SetterMethod = Property->isClassProperty() ?
|
||||||
IMPDecl->getClassMethod(Property->getSetterName()) :
|
IMPDecl->getClassMethod(Property->getSetterName()) :
|
||||||
IMPDecl->getInstanceMethod(Property->getSetterName());
|
IMPDecl->getInstanceMethod(Property->getSetterName());
|
||||||
|
if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
|
||||||
|
GetterMethod = nullptr;
|
||||||
|
if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
|
||||||
|
SetterMethod = nullptr;
|
||||||
LookedUpGetterSetter = true;
|
LookedUpGetterSetter = true;
|
||||||
if (GetterMethod) {
|
if (GetterMethod) {
|
||||||
Diag(GetterMethod->getLocation(),
|
Diag(GetterMethod->getLocation(),
|
||||||
@ -2161,15 +2215,13 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
|
|||||||
Property->getIdentifier(), Property->getQueryKind())) {
|
Property->getIdentifier(), Property->getQueryKind())) {
|
||||||
if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
|
if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
|
||||||
continue;
|
continue;
|
||||||
if (!LookedUpGetterSetter) {
|
GetterMethod = PIDecl->getGetterMethodDecl();
|
||||||
GetterMethod = Property->isClassProperty() ?
|
SetterMethod = PIDecl->getSetterMethodDecl();
|
||||||
IMPDecl->getClassMethod(Property->getGetterName()) :
|
if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
|
||||||
IMPDecl->getInstanceMethod(Property->getGetterName());
|
GetterMethod = nullptr;
|
||||||
SetterMethod = Property->isClassProperty() ?
|
if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
|
||||||
IMPDecl->getClassMethod(Property->getSetterName()) :
|
SetterMethod = nullptr;
|
||||||
IMPDecl->getInstanceMethod(Property->getSetterName());
|
if ((bool)GetterMethod ^ (bool)SetterMethod) {
|
||||||
}
|
|
||||||
if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
|
|
||||||
SourceLocation MethodLoc =
|
SourceLocation MethodLoc =
|
||||||
(GetterMethod ? GetterMethod->getLocation()
|
(GetterMethod ? GetterMethod->getLocation()
|
||||||
: SetterMethod->getLocation());
|
: SetterMethod->getLocation());
|
||||||
@ -2210,8 +2262,10 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D
|
|||||||
for (const auto *PID : D->property_impls()) {
|
for (const auto *PID : D->property_impls()) {
|
||||||
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
||||||
if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
|
if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
|
||||||
!PD->isClassProperty() &&
|
!PD->isClassProperty()) {
|
||||||
!D->getInstanceMethod(PD->getGetterName())) {
|
ObjCMethodDecl *IM = PID->getGetterMethodDecl();
|
||||||
|
if (IM && !IM->isSynthesizedAccessorStub())
|
||||||
|
continue;
|
||||||
ObjCMethodDecl *method = PD->getGetterMethodDecl();
|
ObjCMethodDecl *method = PD->getGetterMethodDecl();
|
||||||
if (!method)
|
if (!method)
|
||||||
continue;
|
continue;
|
||||||
@ -2396,16 +2450,14 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
|
GetterMethod = ObjCMethodDecl::Create(
|
||||||
property->getGetterName(),
|
Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD,
|
||||||
resultTy, nullptr, CD,
|
!IsClassProperty, /*isVariadic=*/false,
|
||||||
!IsClassProperty, /*isVariadic=*/false,
|
/*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
|
||||||
/*isPropertyAccessor=*/true,
|
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
||||||
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
(property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
|
||||||
(property->getPropertyImplementation() ==
|
? ObjCMethodDecl::Optional
|
||||||
ObjCPropertyDecl::Optional) ?
|
: ObjCMethodDecl::Required);
|
||||||
ObjCMethodDecl::Optional :
|
|
||||||
ObjCMethodDecl::Required);
|
|
||||||
CD->addDecl(GetterMethod);
|
CD->addDecl(GetterMethod);
|
||||||
|
|
||||||
AddPropertyAttrs(*this, GetterMethod, property);
|
AddPropertyAttrs(*this, GetterMethod, property);
|
||||||
@ -2447,6 +2499,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
|
|||||||
nullptr, CD, !IsClassProperty,
|
nullptr, CD, !IsClassProperty,
|
||||||
/*isVariadic=*/false,
|
/*isVariadic=*/false,
|
||||||
/*isPropertyAccessor=*/true,
|
/*isPropertyAccessor=*/true,
|
||||||
|
/*isSynthesizedAccessorStub=*/false,
|
||||||
/*isImplicitlyDeclared=*/true,
|
/*isImplicitlyDeclared=*/true,
|
||||||
/*isDefined=*/false,
|
/*isDefined=*/false,
|
||||||
(property->getPropertyImplementation() ==
|
(property->getPropertyImplementation() ==
|
||||||
|
@ -1190,16 +1190,15 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
|
|||||||
true /*instance*/);
|
true /*instance*/);
|
||||||
|
|
||||||
if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
|
if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
|
||||||
AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
|
AtIndexGetter = ObjCMethodDecl::Create(
|
||||||
SourceLocation(), AtIndexGetterSelector,
|
S.Context, SourceLocation(), SourceLocation(), AtIndexGetterSelector,
|
||||||
S.Context.getObjCIdType() /*ReturnType*/,
|
S.Context.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */,
|
||||||
nullptr /*TypeSourceInfo */,
|
S.Context.getTranslationUnitDecl(), true /*Instance*/,
|
||||||
S.Context.getTranslationUnitDecl(),
|
false /*isVariadic*/,
|
||||||
true /*Instance*/, false/*isVariadic*/,
|
/*isPropertyAccessor=*/false,
|
||||||
/*isPropertyAccessor=*/false,
|
/*isSynthesizedAccessorStub=*/false,
|
||||||
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
||||||
ObjCMethodDecl::Required,
|
ObjCMethodDecl::Required, false);
|
||||||
false);
|
|
||||||
ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
|
ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
|
||||||
SourceLocation(), SourceLocation(),
|
SourceLocation(), SourceLocation(),
|
||||||
arrayRef ? &S.Context.Idents.get("index")
|
arrayRef ? &S.Context.Idents.get("index")
|
||||||
@ -1303,6 +1302,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
|
|||||||
ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
|
ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
|
||||||
true /*Instance*/, false /*isVariadic*/,
|
true /*Instance*/, false /*isVariadic*/,
|
||||||
/*isPropertyAccessor=*/false,
|
/*isPropertyAccessor=*/false,
|
||||||
|
/*isSynthesizedAccessorStub=*/false,
|
||||||
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
|
||||||
ObjCMethodDecl::Required, false);
|
ObjCMethodDecl::Required, false);
|
||||||
SmallVector<ParmVarDecl *, 2> Params;
|
SmallVector<ParmVarDecl *, 2> Params;
|
||||||
|
@ -1019,6 +1019,7 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
|
|||||||
MD->setInstanceMethod(Record.readInt());
|
MD->setInstanceMethod(Record.readInt());
|
||||||
MD->setVariadic(Record.readInt());
|
MD->setVariadic(Record.readInt());
|
||||||
MD->setPropertyAccessor(Record.readInt());
|
MD->setPropertyAccessor(Record.readInt());
|
||||||
|
MD->setSynthesizedAccessorStub(Record.readInt());
|
||||||
MD->setDefined(Record.readInt());
|
MD->setDefined(Record.readInt());
|
||||||
MD->setOverriding(Record.readInt());
|
MD->setOverriding(Record.readInt());
|
||||||
MD->setHasSkippedBody(Record.readInt());
|
MD->setHasSkippedBody(Record.readInt());
|
||||||
@ -1313,6 +1314,8 @@ void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
|
|||||||
D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>());
|
D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>());
|
||||||
D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>();
|
D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>();
|
||||||
D->IvarLoc = ReadSourceLocation();
|
D->IvarLoc = ReadSourceLocation();
|
||||||
|
D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
|
||||||
|
D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
|
||||||
D->setGetterCXXConstructor(Record.readExpr());
|
D->setGetterCXXConstructor(Record.readExpr());
|
||||||
D->setSetterCXXAssignment(Record.readExpr());
|
D->setSetterCXXAssignment(Record.readExpr());
|
||||||
}
|
}
|
||||||
|
@ -673,6 +673,7 @@ void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
|||||||
Record.push_back(D->isInstanceMethod());
|
Record.push_back(D->isInstanceMethod());
|
||||||
Record.push_back(D->isVariadic());
|
Record.push_back(D->isVariadic());
|
||||||
Record.push_back(D->isPropertyAccessor());
|
Record.push_back(D->isPropertyAccessor());
|
||||||
|
Record.push_back(D->isSynthesizedAccessorStub());
|
||||||
Record.push_back(D->isDefined());
|
Record.push_back(D->isDefined());
|
||||||
Record.push_back(D->isOverriding());
|
Record.push_back(D->isOverriding());
|
||||||
Record.push_back(D->hasSkippedBody());
|
Record.push_back(D->hasSkippedBody());
|
||||||
@ -884,6 +885,8 @@ void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
|
|||||||
Record.AddDeclRef(D->getPropertyDecl());
|
Record.AddDeclRef(D->getPropertyDecl());
|
||||||
Record.AddDeclRef(D->getPropertyIvarDecl());
|
Record.AddDeclRef(D->getPropertyIvarDecl());
|
||||||
Record.AddSourceLocation(D->getPropertyIvarDeclLoc());
|
Record.AddSourceLocation(D->getPropertyIvarDeclLoc());
|
||||||
|
Record.AddDeclRef(D->getGetterMethodDecl());
|
||||||
|
Record.AddDeclRef(D->getSetterMethodDecl());
|
||||||
Record.AddStmt(D->getGetterCXXConstructor());
|
Record.AddStmt(D->getGetterCXXConstructor());
|
||||||
Record.AddStmt(D->getSetterCXXAssignment());
|
Record.AddStmt(D->getSetterCXXAssignment());
|
||||||
Code = serialization::DECL_OBJC_PROPERTY_IMPL;
|
Code = serialization::DECL_OBJC_PROPERTY_IMPL;
|
||||||
|
@ -144,6 +144,8 @@ void DirectIvarAssignment::checkASTDecl(const ObjCImplementationDecl *D,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Stmt *Body = M->getBody();
|
const Stmt *Body = M->getBody();
|
||||||
|
if (M->isSynthesizedAccessorStub())
|
||||||
|
continue;
|
||||||
assert(Body);
|
assert(Body);
|
||||||
|
|
||||||
MethodCrawler MC(IvarToPropMap, M->getCanonicalDecl(), InterD, BR, this,
|
MethodCrawler MC(IvarToPropMap, M->getCanonicalDecl(), InterD, BR, this,
|
||||||
|
@ -1080,7 +1080,7 @@ ObjCMessageKind ObjCMethodCall::getMessageKind() const {
|
|||||||
|
|
||||||
const ObjCPropertyDecl *ObjCMethodCall::getAccessedProperty() const {
|
const ObjCPropertyDecl *ObjCMethodCall::getAccessedProperty() const {
|
||||||
// Look for properties accessed with property syntax (foo.bar = ...)
|
// Look for properties accessed with property syntax (foo.bar = ...)
|
||||||
if ( getMessageKind() == OCM_PropertyAccess) {
|
if (getMessageKind() == OCM_PropertyAccess) {
|
||||||
const PseudoObjectExpr *POE = getContainingPseudoObjectExpr();
|
const PseudoObjectExpr *POE = getContainingPseudoObjectExpr();
|
||||||
assert(POE && "Property access without PseudoObjectExpr?");
|
assert(POE && "Property access without PseudoObjectExpr?");
|
||||||
|
|
||||||
|
@ -1475,7 +1475,173 @@ void f() {
|
|||||||
// CHECK-NEXT: "qualType": "int"
|
// CHECK-NEXT: "qualType": "int"
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: {
|
||||||
|
// CHECK-NEXT: "id": "0x{{.*}}",
|
||||||
|
// CHECK-NEXT: "kind": "ObjCMethodDecl",
|
||||||
|
// CHECK-NEXT: "loc": {
|
||||||
|
// CHECK-NEXT: "offset": 1109,
|
||||||
|
// CHECK-NEXT: "line": 70,
|
||||||
|
// CHECK-NEXT: "col": 1,
|
||||||
|
// CHECK-NEXT: "tokLen": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "begin": {
|
||||||
|
// CHECK-NEXT: "offset": 1109,
|
||||||
|
// CHECK-NEXT: "col": 1,
|
||||||
|
// CHECK-NEXT: "tokLen": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "offset": 1121,
|
||||||
|
// CHECK-NEXT: "col": 13,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "isImplicit": true,
|
||||||
|
// CHECK-NEXT: "name": "getterFoo",
|
||||||
|
// CHECK-NEXT: "returnType": {
|
||||||
|
// CHECK-NEXT: "qualType": "int"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "instance": true
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: {
|
||||||
|
// CHECK-NEXT: "id": "0x{{.*}}",
|
||||||
|
// CHECK-NEXT: "kind": "ObjCMethodDecl",
|
||||||
|
// CHECK-NEXT: "loc": {
|
||||||
|
// CHECK-NEXT: "offset": 1109,
|
||||||
|
// CHECK-NEXT: "col": 1,
|
||||||
|
// CHECK-NEXT: "tokLen": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "begin": {
|
||||||
|
// CHECK-NEXT: "offset": 1109,
|
||||||
|
// CHECK-NEXT: "col": 1,
|
||||||
|
// CHECK-NEXT: "tokLen": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "offset": 1121,
|
||||||
|
// CHECK-NEXT: "col": 13,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "isImplicit": true,
|
||||||
|
// CHECK-NEXT: "name": "setterFoo:",
|
||||||
|
// CHECK-NEXT: "returnType": {
|
||||||
|
// CHECK-NEXT: "qualType": "void"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "instance": true,
|
||||||
|
// CHECK-NEXT: "inner": [
|
||||||
|
// CHECK-NEXT: {
|
||||||
|
// CHECK-NEXT: "id": "0x{{.*}}",
|
||||||
|
// CHECK-NEXT: "kind": "ParmVarDecl",
|
||||||
|
// CHECK-NEXT: "loc": {
|
||||||
|
// CHECK-NEXT: "offset": 1033,
|
||||||
|
// CHECK-NEXT: "line": 63,
|
||||||
|
// CHECK-NEXT: "col": 52,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "begin": {
|
||||||
|
// CHECK-NEXT: "offset": 1033,
|
||||||
|
// CHECK-NEXT: "col": 52,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "offset": 1033,
|
||||||
|
// CHECK-NEXT: "col": 52,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "name": "foo",
|
||||||
|
// CHECK-NEXT: "type": {
|
||||||
|
// CHECK-NEXT: "qualType": "int"
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: ]
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: {
|
||||||
|
// CHECK-NEXT: "id": "0x{{.*}}",
|
||||||
|
// CHECK-NEXT: "kind": "ObjCMethodDecl",
|
||||||
|
// CHECK-NEXT: "loc": {
|
||||||
|
// CHECK-NEXT: "offset": 1128,
|
||||||
|
// CHECK-NEXT: "line": 71,
|
||||||
|
// CHECK-NEXT: "col": 1,
|
||||||
|
// CHECK-NEXT: "tokLen": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "begin": {
|
||||||
|
// CHECK-NEXT: "offset": 1128,
|
||||||
|
// CHECK-NEXT: "col": 1,
|
||||||
|
// CHECK-NEXT: "tokLen": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "offset": 1140,
|
||||||
|
// CHECK-NEXT: "col": 13,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "isImplicit": true,
|
||||||
|
// CHECK-NEXT: "name": "bar",
|
||||||
|
// CHECK-NEXT: "returnType": {
|
||||||
|
// CHECK-NEXT: "qualType": "int"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "instance": true
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: {
|
||||||
|
// CHECK-NEXT: "id": "0x{{.*}}",
|
||||||
|
// CHECK-NEXT: "kind": "ObjCMethodDecl",
|
||||||
|
// CHECK-NEXT: "loc": {
|
||||||
|
// CHECK-NEXT: "offset": 1128,
|
||||||
|
// CHECK-NEXT: "col": 1,
|
||||||
|
// CHECK-NEXT: "tokLen": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "begin": {
|
||||||
|
// CHECK-NEXT: "offset": 1128,
|
||||||
|
// CHECK-NEXT: "col": 1,
|
||||||
|
// CHECK-NEXT: "tokLen": 1
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "offset": 1140,
|
||||||
|
// CHECK-NEXT: "col": 13,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "isImplicit": true,
|
||||||
|
// CHECK-NEXT: "name": "setBar:",
|
||||||
|
// CHECK-NEXT: "returnType": {
|
||||||
|
// CHECK-NEXT: "qualType": "void"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "instance": true,
|
||||||
|
// CHECK-NEXT: "inner": [
|
||||||
|
// CHECK-NEXT: {
|
||||||
|
// CHECK-NEXT: "id": "0x{{.*}}",
|
||||||
|
// CHECK-NEXT: "kind": "ParmVarDecl",
|
||||||
|
// CHECK-NEXT: "loc": {
|
||||||
|
// CHECK-NEXT: "offset": 1052,
|
||||||
|
// CHECK-NEXT: "line": 64,
|
||||||
|
// CHECK-NEXT: "col": 15,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "range": {
|
||||||
|
// CHECK-NEXT: "begin": {
|
||||||
|
// CHECK-NEXT: "offset": 1052,
|
||||||
|
// CHECK-NEXT: "col": 15,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "end": {
|
||||||
|
// CHECK-NEXT: "offset": 1052,
|
||||||
|
// CHECK-NEXT: "col": 15,
|
||||||
|
// CHECK-NEXT: "tokLen": 3
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: "name": "bar",
|
||||||
|
// CHECK-NEXT: "type": {
|
||||||
|
// CHECK-NEXT: "qualType": "int"
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
// CHECK-NEXT: ]
|
||||||
|
// CHECK-NEXT: }
|
||||||
// CHECK-NEXT: ]
|
// CHECK-NEXT: ]
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
|
|
||||||
|
@ -188,7 +188,6 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>0</key>
|
<key>0</key>
|
||||||
<array>
|
<array>
|
||||||
<integer>10</integer>
|
|
||||||
<integer>14</integer>
|
<integer>14</integer>
|
||||||
<integer>16</integer>
|
<integer>16</integer>
|
||||||
<integer>17</integer>
|
<integer>17</integer>
|
||||||
|
@ -30,8 +30,8 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: ![[FILE:.*]] = !DIFile(filename: "{{[^"]+}}foo.h"
|
// CHECK: ![[FILE:.*]] = !DIFile(filename: "foo.m"
|
||||||
// CHECK: !DISubprogram(name: "-[Foo setDict:]"
|
// CHECK: !DISubprogram(name: "-[Foo setDict:]"
|
||||||
// CHECK-SAME: file: ![[FILE]],
|
// CHECK-SAME: file: ![[FILE]],
|
||||||
// CHECK-SAME: line: 8,
|
// CHECK-SAME: line: 7,
|
||||||
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
@interface I {
|
@interface I {
|
||||||
int _p1;
|
int _p1;
|
||||||
}
|
}
|
||||||
|
@property int p1;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation I
|
||||||
// Test that the linetable entries for the synthesized getter and
|
// Test that the linetable entries for the synthesized getter and
|
||||||
// setter are correct.
|
// setter are correct.
|
||||||
//
|
//
|
||||||
@ -22,10 +26,6 @@
|
|||||||
// CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+3]],
|
// CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+3]],
|
||||||
// CHECK: !DISubprogram(name: "-[I setP1:]",{{.*}} line: [[@LINE+2]],{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
|
// CHECK: !DISubprogram(name: "-[I setP1:]",{{.*}} line: [[@LINE+2]],{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
|
||||||
// CHECK: ![[DBG2]] = !DILocation(line: [[@LINE+1]],
|
// CHECK: ![[DBG2]] = !DILocation(line: [[@LINE+1]],
|
||||||
@property int p1;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation I
|
|
||||||
@synthesize p1 = _p1;
|
@synthesize p1 = _p1;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -11,19 +11,6 @@
|
|||||||
|
|
||||||
@protocol HasASelection <NSObject>
|
@protocol HasASelection <NSObject>
|
||||||
@property (nonatomic, retain) Selection* selection;
|
@property (nonatomic, retain) Selection* selection;
|
||||||
// CHECK: !DISubprogram(name: "-[MyClass selection]"
|
|
||||||
// CHECK-SAME: line: [[@LINE-2]]
|
|
||||||
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
|
||||||
// CHECK: !DISubprogram(name: "-[MyClass setSelection:]"
|
|
||||||
// CHECK-SAME: line: [[@LINE-5]]
|
|
||||||
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
|
||||||
// CHECK: !DISubprogram(name: "-[OtherClass selection]"
|
|
||||||
// CHECK-SAME: line: [[@LINE-8]]
|
|
||||||
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
|
||||||
// CHECK: !DISubprogram(name: "-[OtherClass setSelection:]"
|
|
||||||
// CHECK-SAME: line: [[@LINE-11]]
|
|
||||||
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface MyClass : NSObject <HasASelection> {
|
@interface MyClass : NSObject <HasASelection> {
|
||||||
@ -33,6 +20,12 @@
|
|||||||
|
|
||||||
@implementation MyClass
|
@implementation MyClass
|
||||||
@synthesize selection = _selection;
|
@synthesize selection = _selection;
|
||||||
|
// CHECK: !DISubprogram(name: "-[MyClass selection]"
|
||||||
|
// CHECK-SAME: line: [[@LINE-2]]
|
||||||
|
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
||||||
|
// CHECK: !DISubprogram(name: "-[MyClass setSelection:]"
|
||||||
|
// CHECK-SAME: line: [[@LINE-5]]
|
||||||
|
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface OtherClass : NSObject <HasASelection> {
|
@interface OtherClass : NSObject <HasASelection> {
|
||||||
@ -41,4 +34,10 @@
|
|||||||
@end
|
@end
|
||||||
@implementation OtherClass
|
@implementation OtherClass
|
||||||
@synthesize selection = _selection;
|
@synthesize selection = _selection;
|
||||||
|
// CHECK: !DISubprogram(name: "-[OtherClass selection]"
|
||||||
|
// CHECK-SAME: line: [[@LINE-2]]
|
||||||
|
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
||||||
|
// CHECK: !DISubprogram(name: "-[OtherClass setSelection:]"
|
||||||
|
// CHECK-SAME: line: [[@LINE-5]]
|
||||||
|
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
|
||||||
@end
|
@end
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// REQUIRES: x86-registered-target
|
// REQUIRES: x86-registered-target
|
||||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S -o %t %s
|
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S %s -o - | FileCheck %s
|
||||||
// RUN: FileCheck < %t %s
|
|
||||||
|
|
||||||
// rdar://9072317
|
// rdar://9072317
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ IB_DESIGNABLE @interface I
|
|||||||
|
|
||||||
IBInspectable @property (readonly) IBOutlet NSView *myView1; // expected-warning {{readonly IBOutlet property 'myView1' when auto-synthesized may not work correctly with 'nib' loader}} expected-note {{property should be changed to be readwrite}}
|
IBInspectable @property (readonly) IBOutlet NSView *myView1; // expected-warning {{readonly IBOutlet property 'myView1' when auto-synthesized may not work correctly with 'nib' loader}} expected-note {{property should be changed to be readwrite}}
|
||||||
|
|
||||||
@property (getter = MyGetter, READONLY) IBOutlet NSView *myView2; // expected-warning {{readonly IBOutlet property 'myView2' when auto-synthesized may not work correctly with 'nib' loader}}
|
@property (getter = MyGetter2, READONLY) IBOutlet NSView *myView2; // expected-warning {{readonly IBOutlet property 'myView2' when auto-synthesized may not work correctly with 'nib' loader}}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -629,6 +629,11 @@ bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
|
|||||||
Decl *D = *I;
|
Decl *D = *I;
|
||||||
if (D->getLexicalDeclContext() != DC)
|
if (D->getLexicalDeclContext() != DC)
|
||||||
continue;
|
continue;
|
||||||
|
// Filter out synthesized property accessor redeclarations.
|
||||||
|
if (isa<ObjCImplDecl>(DC))
|
||||||
|
if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
|
||||||
|
if (OMD->isSynthesizedAccessorStub())
|
||||||
|
continue;
|
||||||
const Optional<bool> V = handleDeclForVisitation(D);
|
const Optional<bool> V = handleDeclForVisitation(D);
|
||||||
if (!V.hasValue())
|
if (!V.hasValue())
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user