/// True if this method is the getter or setter for an explicit property.
uint64_t IsPropertyAccessor : 1;
+ /// True if this method is a synthesized property accessor stub.
+ uint64_t IsSynthesizedAccessorStub : 1;
+
/// Method has a definition.
uint64_t IsDefined : 1;
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
DeclContext *contextDecl, bool isInstance = true,
bool isVariadic = false, bool isPropertyAccessor = false,
+ bool isSynthesizedAccessorStub = false,
bool isImplicitlyDeclared = false, bool isDefined = false,
ImplementationControl impControl = None,
bool HasRelatedResultType = false);
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
DeclContext *contextDecl, bool isInstance = true,
bool isVariadic = false, bool isPropertyAccessor = false,
+ bool isSynthesizedAccessorStub = false,
bool isImplicitlyDeclared = false, bool isDefined = false,
ImplementationControl impControl = None,
bool HasRelatedResultType = false);
ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
}
+ bool isSynthesizedAccessorStub() const {
+ return ObjCMethodDeclBits.IsSynthesizedAccessorStub;
+ }
+
+ void setSynthesizedAccessorStub(bool isSynthesizedAccessorStub) {
+ ObjCMethodDeclBits.IsSynthesizedAccessorStub = isSynthesizedAccessorStub;
+ }
+
bool isDefined() const { return ObjCMethodDeclBits.IsDefined; }
void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; }
/// Null for \@dynamic. Required for \@synthesize.
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
/// getter.
Expr *GetterCXXConstructor = nullptr;
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 {
return GetterCXXConstructor;
}
ObjCMethodDecl *ToMethod;
if (GetImportedOrCreateDecl(
- ToMethod, D, Importer.getToContext(), Loc,
- ToEndLoc, Name.getObjCSelector(), ToReturnType,
- ToReturnTypeSourceInfo, DC, D->isInstanceMethod(), D->isVariadic(),
- D->isPropertyAccessor(), D->isImplicit(), D->isDefined(),
+ ToMethod, D, Importer.getToContext(), Loc, ToEndLoc,
+ Name.getObjCSelector(), ToReturnType, ToReturnTypeSourceInfo, DC,
+ D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(),
+ D->isSynthesizedAccessorStub(), D->isImplicit(), D->isDefined(),
D->getImplementationControl(), D->hasRelatedResultType()))
return ToMethod;
// ObjCMethodDecl
//===----------------------------------------------------------------------===//
-ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
- Selector SelInfo, QualType T,
- TypeSourceInfo *ReturnTInfo,
- DeclContext *contextDecl, bool isInstance,
- bool isVariadic, bool isPropertyAccessor,
- bool isImplicitlyDeclared, bool isDefined,
- ImplementationControl impControl,
- bool HasRelatedResultType)
+ObjCMethodDecl::ObjCMethodDecl(
+ SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo,
+ QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl,
+ bool isInstance, bool isVariadic, bool isPropertyAccessor,
+ bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined,
+ ImplementationControl impControl, bool HasRelatedResultType)
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
DeclEndLoc(endLoc) {
setInstanceMethod(isInstance);
setVariadic(isVariadic);
setPropertyAccessor(isPropertyAccessor);
+ setSynthesizedAccessorStub(isSynthesizedAccessorStub);
setDefined(isDefined);
setIsRedeclaration(false);
setHasRedeclaration(false);
ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
DeclContext *contextDecl, bool isInstance, bool isVariadic,
- bool isPropertyAccessor, bool isImplicitlyDeclared, bool isDefined,
- ImplementationControl impControl, bool HasRelatedResultType) {
+ bool isPropertyAccessor, bool isSynthesizedAccessorStub,
+ bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl,
+ bool HasRelatedResultType) {
return new (C, contextDecl) ObjCMethodDecl(
beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance,
- isVariadic, isPropertyAccessor, isImplicitlyDeclared, isDefined,
- impControl, HasRelatedResultType);
+ isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
+ isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
}
ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
if (isPropertyAccessor()) {
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 IsInstance = isInstanceMethod();
}
}
+ 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!");
}
if (D->param_size() != 0)
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);
return Val.getValue();
const ObjCPropertyImplDecl *PID) {
llvm::Constant *AtomicHelperFn =
CodeGenFunction(CGM).GenerateObjCAtomicGetterCopyHelperFunction(PID);
- const ObjCPropertyDecl *PD = PID->getPropertyDecl();
- ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
+ ObjCMethodDecl *OMD = PID->getGetterMethodDecl();
assert(OMD && "Invalid call to generate getter (empty method)");
StartObjCMethod(OMD, IMP->getClassInterface());
const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
QualType propType = prop->getType();
- ObjCMethodDecl *getterMethod = prop->getGetterMethodDecl();
+ ObjCMethodDecl *getterMethod = propImpl->getGetterMethodDecl();
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
const ObjCPropertyImplDecl *propImpl,
llvm::Constant *AtomicHelperFn) {
- const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
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
// non-trivial.
const ObjCPropertyImplDecl *PID) {
llvm::Constant *AtomicHelperFn =
CodeGenFunction(CGM).GenerateObjCAtomicSetterCopyHelperFunction(PID);
- const ObjCPropertyDecl *PD = PID->getPropertyDecl();
- ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
+ ObjCMethodDecl *OMD = PID->getSetterMethodDecl();
assert(OMD && "Invalid call to generate setter (empty method)");
StartObjCMethod(OMD, IMP->getClassInterface());
for (auto *propImpl : OID->property_impls())
if (propImpl->getPropertyImplementation() ==
ObjCPropertyImplDecl::Synthesize) {
- ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
- auto addIfExists = [&](const ObjCMethodDecl* OMD) {
- if (OMD)
+ auto addIfExists = [&](const ObjCMethodDecl *OMD) {
+ if (OMD && OMD->hasBody())
InstanceMethods.push_back(OMD);
};
- addIfExists(prop->getGetterMethodDecl());
- addIfExists(prop->getSetterMethodDecl());
+ addIfExists(propImpl->getGetterMethodDecl());
+ addIfExists(propImpl->getSetterMethodDecl());
}
if (InstanceMethods.size() == 0)
for (auto *propertyImpl : OID->property_impls())
if (propertyImpl->getPropertyImplementation() ==
ObjCPropertyImplDecl::Synthesize) {
- ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
if (accessor)
InstanceMethods.push_back(accessor);
};
- addPropertyMethod(property->getGetterMethodDecl());
- addPropertyMethod(property->getSetterMethodDecl());
+ addPropertyMethod(propertyImpl->getGetterMethodDecl());
+ addPropertyMethod(propertyImpl->getSetterMethodDecl());
}
llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
for (const auto *PID : ID->property_impls()) {
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
- ObjCPropertyDecl *PD = PID->getPropertyDecl();
-
- if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
+ if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
if (GetMethodDefinition(MD))
Methods[InstanceMethods].push_back(MD);
- if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
+ if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
if (GetMethodDefinition(MD))
Methods[InstanceMethods].push_back(MD);
}
} else {
for (const auto *MD : ID->instance_methods())
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(),
// method_count
values.addInt(ObjCTypes.IntTy, methods.size());
auto methodArray = values.beginArray(ObjCTypes.MethodTy);
- for (auto MD : methods) {
+ for (auto MD : methods)
emitMethodConstant(methodArray, MD, forProtocol);
- }
methodArray.finishAndAddTo(values);
llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM);
}
-void CodeGenFunction::StartFunction(GlobalDecl GD,
- QualType RetTy,
+void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
llvm::Function *Fn,
const CGFunctionInfo &FnInfo,
const FunctionArgList &Args,
// we want, that just indicates if the decl came from a
// property. What we want to know is if the method is defined in
// this implementation.
- if (!D->getInstanceMethod(PD->getGetterName()))
+ auto *Getter = PID->getGetterMethodDecl();
+ if (!Getter || Getter->isSynthesizedAccessorStub())
CodeGenFunction(*this).GenerateObjCGetter(
- const_cast<ObjCImplementationDecl *>(D), PID);
- if (!PD->isReadOnly() &&
- !D->getInstanceMethod(PD->getSetterName()))
+ const_cast<ObjCImplementationDecl *>(D), PID);
+ auto *Setter = PID->getSetterMethodDecl();
+ if (!PD->isReadOnly() && (!Setter || Setter->isSynthesizedAccessorStub()))
CodeGenFunction(*this).GenerateObjCSetter(
const_cast<ObjCImplementationDecl *>(D), PID);
}
if (needsDestructMethod(D)) {
IdentifierInfo *II = &getContext().Idents.get(".cxx_destruct");
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
- ObjCMethodDecl *DTORMethod =
- ObjCMethodDecl::Create(getContext(), D->getLocation(), D->getLocation(),
- cxxSelector, getContext().VoidTy, nullptr, D,
- /*isInstance=*/true, /*isVariadic=*/false,
- /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true,
- /*isDefined=*/false, ObjCMethodDecl::Required);
+ ObjCMethodDecl *DTORMethod = ObjCMethodDecl::Create(
+ getContext(), D->getLocation(), D->getLocation(), cxxSelector,
+ getContext().VoidTy, nullptr, D,
+ /*isInstance=*/true, /*isVariadic=*/false,
+ /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false, ObjCMethodDecl::Required);
D->addInstanceMethod(DTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
D->setHasDestructors(true);
IdentifierInfo *II = &getContext().Idents.get(".cxx_construct");
Selector cxxSelector = getContext().Selectors.getSelector(0, &II);
// The constructor returns 'self'.
- ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(getContext(),
- D->getLocation(),
- D->getLocation(),
- cxxSelector,
- getContext().getObjCIdType(),
- nullptr, D, /*isInstance=*/true,
- /*isVariadic=*/false,
- /*isPropertyAccessor=*/true,
- /*isImplicitlyDeclared=*/true,
- /*isDefined=*/false,
- ObjCMethodDecl::Required);
+ ObjCMethodDecl *CTORMethod = ObjCMethodDecl::Create(
+ getContext(), D->getLocation(), D->getLocation(), cxxSelector,
+ getContext().getObjCIdType(), nullptr, D, /*isInstance=*/true,
+ /*isVariadic=*/false,
+ /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false, ObjCMethodDecl::Required);
D->addInstanceMethod(CTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
D->setHasNonZeroConstructors(true);
static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,
ObjCPropertyDecl *PD,
bool getter) {
- return getter ? !IMP->getInstanceMethod(PD->getGetterName())
- : !IMP->getInstanceMethod(PD->getSetterName());
-
+ auto *OMD = IMP->getInstanceMethod(getter ? PD->getGetterName()
+ : PD->getSetterName());
+ return !OMD || OMD->isSynthesizedAccessorStub();
}
void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
"id objc_getProperty(id, SEL, long, bool);\n";
}
RewriteObjCMethodDecl(OID->getContainingInterface(),
- PD->getGetterMethodDecl(), Getr);
+ PID->getGetterMethodDecl(), Getr);
Getr += "{ ";
// Synthesize an explicit cast to gain access to the ivar.
// See objc-act.c:objc_synthesize_new_getter() for details.
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
Getr += "typedef ";
const FunctionType *FPRetType = nullptr;
- RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr,
+ RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,
FPRetType);
Getr += " _TYPE";
if (FPRetType) {
}
RewriteObjCMethodDecl(OID->getContainingInterface(),
- PD->getSetterMethodDecl(), Setr);
+ PID->getSetterMethodDecl(), Setr);
Setr += "{ ";
// Synthesize an explicit cast to initialize the ivar.
// See objc-act.c:objc_synthesize_new_setter() for details.
InsertText(CID->getBeginLoc(), "// ");
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
+ if (!OMD->getBody())
+ continue;
std::string ResultStr;
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
SourceLocation LocStart = OMD->getBeginLoc();
}
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
+ if (!OMD->getBody())
+ continue;
std::string ResultStr;
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
SourceLocation LocStart = OMD->getBeginLoc();
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
if (!PD)
continue;
- if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+ if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))
InstanceMethods.push_back(Getter);
if (PD->isReadOnly())
continue;
- if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+ if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))
InstanceMethods.push_back(Setter);
}
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
if (!PD)
continue;
- if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+ if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
InstanceMethods.push_back(Getter);
if (PD->isReadOnly())
continue;
- if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+ if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
InstanceMethods.push_back(Setter);
}
if (!OID)
return;
+
unsigned Attributes = PD->getPropertyAttributes();
- if (!PD->getGetterMethodDecl()->isDefined()) {
+ if (PID->getGetterMethodDecl() && !PID->getGetterMethodDecl()->isDefined()) {
bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
(Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy));
"id objc_getProperty(id, SEL, long, bool);\n";
}
RewriteObjCMethodDecl(OID->getContainingInterface(),
- PD->getGetterMethodDecl(), Getr);
+ PID->getGetterMethodDecl(), Getr);
Getr += "{ ";
// Synthesize an explicit cast to gain access to the ivar.
// See objc-act.c:objc_synthesize_new_getter() for details.
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
Getr += "typedef ";
const FunctionType *FPRetType = nullptr;
- RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr,
+ RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,
FPRetType);
Getr += " _TYPE";
if (FPRetType) {
InsertText(onePastSemiLoc, Getr);
}
- if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined())
+ if (PD->isReadOnly() || !PID->getSetterMethodDecl() ||
+ PID->getSetterMethodDecl()->isDefined())
return;
// Generate the 'setter' function.
}
RewriteObjCMethodDecl(OID->getContainingInterface(),
- PD->getSetterMethodDecl(), Setr);
+ PID->getSetterMethodDecl(), Setr);
Setr += "{ ";
// Synthesize an explicit cast to initialize the ivar.
// See objc-act.c:objc_synthesize_new_setter() for details.
InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// ");
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
+ if (!OMD->getBody())
+ continue;
std::string ResultStr;
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
SourceLocation LocStart = OMD->getBeginLoc();
}
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
+ if (!OMD->getBody())
+ continue;
std::string ResultStr;
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
SourceLocation LocStart = OMD->getBeginLoc();
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
if (!PD)
continue;
- if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+ if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
if (!Getter->isDefined())
InstanceMethods.push_back(Getter);
if (PD->isReadOnly())
continue;
- if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+ if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
if (!Setter->isDefined())
InstanceMethods.push_back(Setter);
}
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
if (!PD)
continue;
- if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
+ if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
InstanceMethods.push_back(Getter);
if (PD->isReadOnly())
continue;
- if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl())
+ if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
InstanceMethods.push_back(Setter);
}
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
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,
const NamedDecl *Parent,
const DeclContext *DC) {
}
}
+ /// 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,
const NamedDecl *Parent = nullptr,
bool isIBType = false) {
SymbolRoleSet AccessorMethodRoles =
SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
- if (MD->isPropertyAccessor() &&
- !hasUserDefined(MD, Container))
+ if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
}
if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
- if (MD->isPropertyAccessor() &&
- !hasUserDefined(MD, Container))
+ if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
}
if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
"Expected to find the method through lookup as well");
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl) {
+ // Skip property accessor function stubs.
+ if (ImpMethodDecl->isSynthesizedAccessorStub())
+ continue;
if (!WarnCategoryMethodImpl)
WarnConflictingTypedMethods(ImpMethodDecl, I,
isa<ObjCProtocolDecl>(CDecl));
"Expected to find the method through lookup as well");
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl) {
+ // Skip property accessor function stubs.
+ if (ImpMethodDecl->isSynthesizedAccessorStub())
+ continue;
if (!WarnCategoryMethodImpl)
WarnConflictingTypedMethods(ImpMethodDecl, I,
isa<ObjCProtocolDecl>(CDecl));
|| isa<ObjCProtocolDecl>(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.
llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;
continue;
for (const auto *Ext : IDecl->visible_extensions()) {
- if (ObjCMethodDecl *GetterMethod
- = Ext->getInstanceMethod(Property->getGetterName()))
+ if (ObjCMethodDecl *GetterMethod =
+ Ext->getInstanceMethod(Property->getGetterName()))
GetterMethod->setPropertyAccessor(true);
if (!Property->isReadOnly())
if (ObjCMethodDecl *SetterMethod
Diag(MethodLoc, diag::err_missing_method_context);
return nullptr;
}
+
Decl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
QualType resultDeclType;
ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create(
Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, CurContext,
MethodType == tok::minus, isVariadic,
- /*isPropertyAccessor=*/false,
+ /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,
/*isImplicitlyDeclared=*/false, /*isDefined=*/false,
MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional
: ObjCMethodDecl::Required,
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
// @implementation.
if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) {
if (!IV)
continue;
+ if (CurMethod->isSynthesizedAccessorStub())
+ continue;
+
UnusedBackingIvarChecker Checker(*this, CurMethod, IV);
Checker.TraverseStmt(CurMethod->getBody());
if (Checker.AccessedIvar)
S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl,
/*isInstance=*/false, /*isVariadic=*/false,
/*isPropertyAccessor=*/false,
+ /*isSynthesizedAccessorStub=*/false,
/*isImplicitlyDeclared=*/true,
/*isDefined=*/false, ObjCMethodDecl::Required,
/*HasRelatedResultType=*/false);
NSStringPointer, ReturnTInfo, NSStringDecl,
/*isInstance=*/false, /*isVariadic=*/false,
/*isPropertyAccessor=*/false,
+ /*isSynthesizedAccessorStub=*/false,
/*isImplicitlyDeclared=*/true,
/*isDefined=*/false, ObjCMethodDecl::Required,
/*HasRelatedResultType=*/false);
// Debugger needs to work even if NSValue hasn't been defined.
TypeSourceInfo *ReturnTInfo = nullptr;
ObjCMethodDecl *M = ObjCMethodDecl::Create(
- Context,
- SourceLocation(),
- SourceLocation(),
- ValueWithBytesObjCType,
- NSValuePointer,
- ReturnTInfo,
- NSValueDecl,
- /*isInstance=*/false,
- /*isVariadic=*/false,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true,
- /*isDefined=*/false,
- ObjCMethodDecl::Required,
- /*HasRelatedResultType=*/false);
+ Context, SourceLocation(), SourceLocation(), ValueWithBytesObjCType,
+ NSValuePointer, ReturnTInfo, NSValueDecl,
+ /*isInstance=*/false,
+ /*isVariadic=*/false,
+ /*isPropertyAccessor=*/false,
+ /*isSynthesizedAccessorStub=*/false,
+ /*isImplicitlyDeclared=*/true,
+ /*isDefined=*/false, ObjCMethodDecl::Required,
+ /*HasRelatedResultType=*/false);
SmallVector<ParmVarDecl *, 2> Params;
Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,
Context.getTranslationUnitDecl(), false /*Instance*/,
false /*isVariadic*/,
- /*isPropertyAccessor=*/false,
+ /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
ObjCMethodDecl::Required, false);
SmallVector<ParmVarDecl *, 2> Params;
NSAPI::NSDict_dictionaryWithObjectsForKeysCount);
ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel);
if (!Method && getLangOpts().DebuggerObjCLiteral) {
- Method = ObjCMethodDecl::Create(Context,
- SourceLocation(), SourceLocation(), Sel,
- IdT,
- nullptr /*TypeSourceInfo */,
- Context.getTranslationUnitDecl(),
- false /*Instance*/, false/*isVariadic*/,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
- ObjCMethodDecl::Required,
- false);
+ Method = ObjCMethodDecl::Create(
+ Context, SourceLocation(), SourceLocation(), Sel, IdT,
+ nullptr /*TypeSourceInfo */, Context.getTranslationUnitDecl(),
+ false /*Instance*/, false /*isVariadic*/,
+ /*isPropertyAccessor=*/false,
+ /*isSynthesizedAccessorStub=*/false,
+ /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+ ObjCMethodDecl::Required, false);
SmallVector<ParmVarDecl *, 3> Params;
ParmVarDecl *objects = ParmVarDecl::Create(Context, Method,
SourceLocation(),
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
/// builds the AST node for a property implementation declaration; declared
/// as \@synthesize or \@dynamic.
if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
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 &&
Ivar->getType()->isRecordType()) {
// For Objective-C++, need to synthesize the AST for the IVAR object to be
break;
}
}
+
if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
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 &&
Ivar->getType()->isRecordType()) {
// FIXME. Eventually we want to do this for Objective-C as well.
if (IMPDecl->FindPropertyImplDecl(
Prop->getIdentifier(), Prop->getQueryKind()))
continue;
- if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
+ ObjCMethodDecl *ImpMethod = IMPDecl->getInstanceMethod(Prop->getGetterName());
+ if (ImpMethod && !ImpMethod->getBody()) {
if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
continue;
- if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
+ ImpMethod = IMPDecl->getInstanceMethod(Prop->getSetterName());
+ if (ImpMethod && !ImpMethod->getBody())
continue;
}
if (ObjCPropertyImplDecl *PID =
void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) {
for (const auto *propertyImpl : impDecl->property_impls()) {
const auto *property = propertyImpl->getPropertyDecl();
-
// Warn about null_resettable properties with synthesized setters,
// because the setter won't properly handle nil.
if (propertyImpl->getPropertyImplementation()
ObjCPropertyDecl::OBJC_PR_null_resettable) &&
property->getGetterMethodDecl() &&
property->getSetterMethodDecl()) {
- auto *getterMethod = property->getGetterMethodDecl();
- auto *setterMethod = property->getSetterMethodDecl();
- if (!impDecl->getInstanceMethod(setterMethod->getSelector()) &&
- !impDecl->getInstanceMethod(getterMethod->getSelector())) {
+ auto *getterImpl = propertyImpl->getGetterMethodDecl();
+ auto *setterImpl = propertyImpl->getSetterMethodDecl();
+ if ((!getterImpl || getterImpl->isSynthesizedAccessorStub()) &&
+ (!setterImpl || setterImpl->isSynthesizedAccessorStub())) {
SourceLocation loc = propertyImpl->getLocation();
if (loc.isInvalid())
loc = impDecl->getBeginLoc();
Diag(loc, diag::warn_null_resettable_setter)
- << setterMethod->getSelector() << property->getDeclName();
+ << setterImpl->getSelector() << property->getDeclName();
}
}
}
SetterMethod = Property->isClassProperty() ?
IMPDecl->getClassMethod(Property->getSetterName()) :
IMPDecl->getInstanceMethod(Property->getSetterName());
+ if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
+ GetterMethod = nullptr;
+ if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
+ SetterMethod = nullptr;
LookedUpGetterSetter = true;
if (GetterMethod) {
Diag(GetterMethod->getLocation(),
Property->getIdentifier(), Property->getQueryKind())) {
if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
continue;
- if (!LookedUpGetterSetter) {
- GetterMethod = Property->isClassProperty() ?
- IMPDecl->getClassMethod(Property->getGetterName()) :
- IMPDecl->getInstanceMethod(Property->getGetterName());
- SetterMethod = Property->isClassProperty() ?
- IMPDecl->getClassMethod(Property->getSetterName()) :
- IMPDecl->getInstanceMethod(Property->getSetterName());
- }
- if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
+ GetterMethod = PIDecl->getGetterMethodDecl();
+ SetterMethod = PIDecl->getSetterMethodDecl();
+ if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
+ GetterMethod = nullptr;
+ if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
+ SetterMethod = nullptr;
+ if ((bool)GetterMethod ^ (bool)SetterMethod) {
SourceLocation MethodLoc =
(GetterMethod ? GetterMethod->getLocation()
: SetterMethod->getLocation());
for (const auto *PID : D->property_impls()) {
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
- !PD->isClassProperty() &&
- !D->getInstanceMethod(PD->getGetterName())) {
+ !PD->isClassProperty()) {
+ ObjCMethodDecl *IM = PID->getGetterMethodDecl();
+ if (IM && !IM->isSynthesizedAccessorStub())
+ continue;
ObjCMethodDecl *method = PD->getGetterMethodDecl();
if (!method)
continue;
}
}
- GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
- property->getGetterName(),
- resultTy, nullptr, CD,
- !IsClassProperty, /*isVariadic=*/false,
- /*isPropertyAccessor=*/true,
- /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
- (property->getPropertyImplementation() ==
- ObjCPropertyDecl::Optional) ?
- ObjCMethodDecl::Optional :
- ObjCMethodDecl::Required);
+ GetterMethod = ObjCMethodDecl::Create(
+ Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD,
+ !IsClassProperty, /*isVariadic=*/false,
+ /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
+ /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+ (property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
+ ? ObjCMethodDecl::Optional
+ : ObjCMethodDecl::Required);
CD->addDecl(GetterMethod);
AddPropertyAttrs(*this, GetterMethod, property);
nullptr, CD, !IsClassProperty,
/*isVariadic=*/false,
/*isPropertyAccessor=*/true,
+ /*isSynthesizedAccessorStub=*/false,
/*isImplicitlyDeclared=*/true,
/*isDefined=*/false,
(property->getPropertyImplementation() ==
true /*instance*/);
if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
- AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
- SourceLocation(), AtIndexGetterSelector,
- S.Context.getObjCIdType() /*ReturnType*/,
- nullptr /*TypeSourceInfo */,
- S.Context.getTranslationUnitDecl(),
- true /*Instance*/, false/*isVariadic*/,
- /*isPropertyAccessor=*/false,
- /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
- ObjCMethodDecl::Required,
- false);
+ AtIndexGetter = ObjCMethodDecl::Create(
+ S.Context, SourceLocation(), SourceLocation(), AtIndexGetterSelector,
+ S.Context.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */,
+ S.Context.getTranslationUnitDecl(), true /*Instance*/,
+ false /*isVariadic*/,
+ /*isPropertyAccessor=*/false,
+ /*isSynthesizedAccessorStub=*/false,
+ /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+ ObjCMethodDecl::Required, false);
ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
SourceLocation(), SourceLocation(),
arrayRef ? &S.Context.Idents.get("index")
ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
true /*Instance*/, false /*isVariadic*/,
/*isPropertyAccessor=*/false,
+ /*isSynthesizedAccessorStub=*/false,
/*isImplicitlyDeclared=*/true, /*isDefined=*/false,
ObjCMethodDecl::Required, false);
SmallVector<ParmVarDecl *, 2> Params;
MD->setInstanceMethod(Record.readInt());
MD->setVariadic(Record.readInt());
MD->setPropertyAccessor(Record.readInt());
+ MD->setSynthesizedAccessorStub(Record.readInt());
MD->setDefined(Record.readInt());
MD->setOverriding(Record.readInt());
MD->setHasSkippedBody(Record.readInt());
D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>());
D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>();
D->IvarLoc = ReadSourceLocation();
+ D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
+ D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
D->setGetterCXXConstructor(Record.readExpr());
D->setSetterCXXAssignment(Record.readExpr());
}
Record.push_back(D->isInstanceMethod());
Record.push_back(D->isVariadic());
Record.push_back(D->isPropertyAccessor());
+ Record.push_back(D->isSynthesizedAccessorStub());
Record.push_back(D->isDefined());
Record.push_back(D->isOverriding());
Record.push_back(D->hasSkippedBody());
Record.AddDeclRef(D->getPropertyDecl());
Record.AddDeclRef(D->getPropertyIvarDecl());
Record.AddSourceLocation(D->getPropertyIvarDeclLoc());
+ Record.AddDeclRef(D->getGetterMethodDecl());
+ Record.AddDeclRef(D->getSetterMethodDecl());
Record.AddStmt(D->getGetterCXXConstructor());
Record.AddStmt(D->getSetterCXXAssignment());
Code = serialization::DECL_OBJC_PROPERTY_IMPL;
continue;
const Stmt *Body = M->getBody();
+ if (M->isSynthesizedAccessorStub())
+ continue;
assert(Body);
MethodCrawler MC(IvarToPropMap, M->getCanonicalDecl(), InterD, BR, this,
const ObjCPropertyDecl *ObjCMethodCall::getAccessedProperty() const {
// Look for properties accessed with property syntax (foo.bar = ...)
- if ( getMessageKind() == OCM_PropertyAccess) {
+ if (getMessageKind() == OCM_PropertyAccess) {
const PseudoObjectExpr *POE = getContainingPseudoObjectExpr();
assert(POE && "Property access without PseudoObjectExpr?");
// 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": 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: }
<dict>
<key>0</key>
<array>
- <integer>10</integer>
<integer>14</integer>
<integer>16</integer>
<integer>17</integer>
}
}
-// CHECK: ![[FILE:.*]] = !DIFile(filename: "{{[^"]+}}foo.h"
+// CHECK: ![[FILE:.*]] = !DIFile(filename: "foo.m"
// CHECK: !DISubprogram(name: "-[Foo setDict:]"
// CHECK-SAME: file: ![[FILE]],
-// CHECK-SAME: line: 8,
+// CHECK-SAME: line: 7,
// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition
@interface I {
int _p1;
}
+@property int p1;
+@end
+
+@implementation I
// Test that the linetable entries for the synthesized getter and
// setter are correct.
//
// CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+3]],
// CHECK: !DISubprogram(name: "-[I setP1:]",{{.*}} line: [[@LINE+2]],{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK: ![[DBG2]] = !DILocation(line: [[@LINE+1]],
-@property int p1;
-@end
-
-@implementation I
@synthesize p1 = _p1;
@end
@protocol HasASelection <NSObject>
@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
@interface MyClass : NSObject <HasASelection> {
@implementation MyClass
@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
@interface OtherClass : NSObject <HasASelection> {
@end
@implementation OtherClass
@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
// REQUIRES: x86-registered-target
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S -o %t %s
-// RUN: FileCheck < %t %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S %s -o - | FileCheck %s
// rdar://9072317
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
Decl *D = *I;
if (D->getLexicalDeclContext() != DC)
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);
if (!V.hasValue())
continue;