Skip to content

Commit a721fbb

Browse files
Merge pull request #269 from adrian-prantl/53782400
Cherry-pick bugfixes for rdar://53782400
2 parents 6e486b6 + 3282e7e commit a721fbb

32 files changed

+583
-222
lines changed

clang/include/clang/AST/DeclBase.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,6 +1583,9 @@ class DeclContext {
15831583
/// True if this method is the getter or setter for an explicit property.
15841584
uint64_t IsPropertyAccessor : 1;
15851585

1586+
/// True if this method is a synthesized property accessor stub.
1587+
uint64_t IsSynthesizedAccessorStub : 1;
1588+
15861589
/// Method has a definition.
15871590
uint64_t IsDefined : 1;
15881591

clang/include/clang/AST/DeclObjC.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
172172
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
173173
DeclContext *contextDecl, bool isInstance = true,
174174
bool isVariadic = false, bool isPropertyAccessor = false,
175+
bool isSynthesizedAccessorStub = false,
175176
bool isImplicitlyDeclared = false, bool isDefined = false,
176177
ImplementationControl impControl = None,
177178
bool HasRelatedResultType = false);
@@ -232,6 +233,7 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
232233
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
233234
DeclContext *contextDecl, bool isInstance = true,
234235
bool isVariadic = false, bool isPropertyAccessor = false,
236+
bool isSynthesizedAccessorStub = false,
235237
bool isImplicitlyDeclared = false, bool isDefined = false,
236238
ImplementationControl impControl = None,
237239
bool HasRelatedResultType = false);
@@ -436,6 +438,14 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
436438
ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
437439
}
438440

441+
bool isSynthesizedAccessorStub() const {
442+
return ObjCMethodDeclBits.IsSynthesizedAccessorStub;
443+
}
444+
445+
void setSynthesizedAccessorStub(bool isSynthesizedAccessorStub) {
446+
ObjCMethodDeclBits.IsSynthesizedAccessorStub = isSynthesizedAccessorStub;
447+
}
448+
439449
bool isDefined() const { return ObjCMethodDeclBits.IsDefined; }
440450
void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; }
441451

@@ -2808,6 +2818,11 @@ class ObjCPropertyImplDecl : public Decl {
28082818
/// Null for \@dynamic. Required for \@synthesize.
28092819
ObjCIvarDecl *PropertyIvarDecl;
28102820

2821+
/// The getter's definition, which has an empty body if synthesized.
2822+
ObjCMethodDecl *GetterMethodDecl = nullptr;
2823+
/// The getter's definition, which has an empty body if synthesized.
2824+
ObjCMethodDecl *SetterMethodDecl = nullptr;
2825+
28112826
/// Null for \@dynamic. Non-null if property must be copy-constructed in
28122827
/// getter.
28132828
Expr *GetterCXXConstructor = nullptr;
@@ -2874,6 +2889,12 @@ class ObjCPropertyImplDecl : public Decl {
28742889
return IvarLoc.isValid() && IvarLoc != getLocation();
28752890
}
28762891

2892+
ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
2893+
void setGetterMethodDecl(ObjCMethodDecl *MD) { GetterMethodDecl = MD; }
2894+
2895+
ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
2896+
void setSetterMethodDecl(ObjCMethodDecl *MD) { SetterMethodDecl = MD; }
2897+
28772898
Expr *getGetterCXXConstructor() const {
28782899
return GetterCXXConstructor;
28792900
}

clang/lib/AST/ASTImporter.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3989,10 +3989,10 @@ ExpectedDecl ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
39893989

39903990
ObjCMethodDecl *ToMethod;
39913991
if (GetImportedOrCreateDecl(
3992-
ToMethod, D, Importer.getToContext(), Loc,
3993-
ToEndLoc, Name.getObjCSelector(), ToReturnType,
3994-
ToReturnTypeSourceInfo, DC, D->isInstanceMethod(), D->isVariadic(),
3995-
D->isPropertyAccessor(), D->isImplicit(), D->isDefined(),
3992+
ToMethod, D, Importer.getToContext(), Loc, ToEndLoc,
3993+
Name.getObjCSelector(), ToReturnType, ToReturnTypeSourceInfo, DC,
3994+
D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(),
3995+
D->isSynthesizedAccessorStub(), D->isImplicit(), D->isDefined(),
39963996
D->getImplementationControl(), D->hasRelatedResultType()))
39973997
return ToMethod;
39983998

clang/lib/AST/DeclObjC.cpp

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -775,14 +775,12 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
775775
// ObjCMethodDecl
776776
//===----------------------------------------------------------------------===//
777777

778-
ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
779-
Selector SelInfo, QualType T,
780-
TypeSourceInfo *ReturnTInfo,
781-
DeclContext *contextDecl, bool isInstance,
782-
bool isVariadic, bool isPropertyAccessor,
783-
bool isImplicitlyDeclared, bool isDefined,
784-
ImplementationControl impControl,
785-
bool HasRelatedResultType)
778+
ObjCMethodDecl::ObjCMethodDecl(
779+
SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo,
780+
QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl,
781+
bool isInstance, bool isVariadic, bool isPropertyAccessor,
782+
bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined,
783+
ImplementationControl impControl, bool HasRelatedResultType)
786784
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
787785
DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
788786
DeclEndLoc(endLoc) {
@@ -793,6 +791,7 @@ ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
793791
setInstanceMethod(isInstance);
794792
setVariadic(isVariadic);
795793
setPropertyAccessor(isPropertyAccessor);
794+
setSynthesizedAccessorStub(isSynthesizedAccessorStub);
796795
setDefined(isDefined);
797796
setIsRedeclaration(false);
798797
setHasRedeclaration(false);
@@ -810,12 +809,13 @@ ObjCMethodDecl *ObjCMethodDecl::Create(
810809
ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
811810
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
812811
DeclContext *contextDecl, bool isInstance, bool isVariadic,
813-
bool isPropertyAccessor, bool isImplicitlyDeclared, bool isDefined,
814-
ImplementationControl impControl, bool HasRelatedResultType) {
812+
bool isPropertyAccessor, bool isSynthesizedAccessorStub,
813+
bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl,
814+
bool HasRelatedResultType) {
815815
return new (C, contextDecl) ObjCMethodDecl(
816816
beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance,
817-
isVariadic, isPropertyAccessor, isImplicitlyDeclared, isDefined,
818-
impControl, HasRelatedResultType);
817+
isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
818+
isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
819819
}
820820

821821
ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
@@ -1306,6 +1306,11 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
13061306

13071307
if (isPropertyAccessor()) {
13081308
const auto *Container = cast<ObjCContainerDecl>(getParent());
1309+
// For accessor stubs, go back to the interface.
1310+
if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container))
1311+
if (isSynthesizedAccessorStub())
1312+
Container = ImplDecl->getClassInterface();
1313+
13091314
bool IsGetter = (NumArgs == 0);
13101315
bool IsInstance = isInstanceMethod();
13111316

@@ -1358,6 +1363,15 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
13581363
}
13591364
}
13601365

1366+
assert(isSynthesizedAccessorStub() && "expected an accessor stub");
1367+
for (const auto *Cat : ClassDecl->known_categories()) {
1368+
if (Cat == Container)
1369+
continue;
1370+
1371+
if (const auto *Found = findMatchingProperty(Cat))
1372+
return Found;
1373+
}
1374+
13611375
llvm_unreachable("Marked as a property accessor but no property found!");
13621376
}
13631377

clang/lib/Analysis/BodyFarm.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,16 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
830830
if (D->param_size() != 0)
831831
return nullptr;
832832

833+
// If the property was defined in an extension, search the extensions for
834+
// overrides.
835+
const ObjCInterfaceDecl *OID = D->getClassInterface();
836+
if (dyn_cast<ObjCInterfaceDecl>(D->getParent()) != OID)
837+
for (auto *Ext : OID->known_extensions()) {
838+
auto *OMD = Ext->getInstanceMethod(D->getSelector());
839+
if (OMD && !OMD->isImplicit())
840+
return nullptr;
841+
}
842+
833843
Val = createObjCPropertyGetter(C, Prop);
834844

835845
return Val.getValue();

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2569,8 +2569,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty,
25692569
SourceLocation Loc = PD->getLocation();
25702570
llvm::DIFile *PUnit = getOrCreateFile(Loc);
25712571
unsigned PLine = getLineNumber(Loc);
2572-
ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
2573-
ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
2572+
ObjCMethodDecl *Getter = PImpD->getGetterMethodDecl();
2573+
ObjCMethodDecl *Setter = PImpD->getSetterMethodDecl();
25742574
PropertyNode = DBuilder.createObjCProperty(
25752575
PD->getName(), PUnit, PLine,
25762576
hasDefaultGetterName(PD, Getter)
@@ -3445,6 +3445,38 @@ llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) {
34453445
return nullptr;
34463446
}
34473447

3448+
llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration(
3449+
const Decl *D, llvm::DISubroutineType *FnType, unsigned LineNo,
3450+
llvm::DINode::DIFlags Flags, llvm::DISubprogram::DISPFlags SPFlags) {
3451+
if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly)
3452+
return nullptr;
3453+
3454+
if (CGM.getCodeGenOpts().DwarfVersion < 5)
3455+
return nullptr;
3456+
3457+
// Starting with DWARF V5 method declarations are emitted as children of
3458+
// the interface type.
3459+
const auto *OMD = dyn_cast<ObjCMethodDecl>(D);
3460+
if (!OMD)
3461+
return nullptr;
3462+
auto *ID = dyn_cast_or_null<ObjCInterfaceDecl>(D->getDeclContext());
3463+
if (!ID)
3464+
ID = OMD->getClassInterface();
3465+
if (!ID)
3466+
return nullptr;
3467+
QualType QTy(ID->getTypeForDecl(), 0);
3468+
auto It = TypeCache.find(QTy.getAsOpaquePtr());
3469+
if (It == TypeCache.end())
3470+
return nullptr;
3471+
auto *InterfaceType = cast<llvm::DICompositeType>(It->second);
3472+
llvm::DISubprogram *FD = DBuilder.createFunction(
3473+
InterfaceType, getObjCMethodName(OMD), StringRef(),
3474+
InterfaceType->getFile(), LineNo, FnType, LineNo, Flags, SPFlags);
3475+
DBuilder.finalizeSubprogram(FD);
3476+
ObjCMethodCache[ID].push_back(FD);
3477+
return FD;
3478+
}
3479+
34483480
// getOrCreateFunctionType - Construct type. If it is a c++ method, include
34493481
// implicit parameter "this".
34503482
llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
@@ -3587,43 +3619,28 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc,
35873619

35883620
unsigned LineNo = getLineNumber(Loc);
35893621
unsigned ScopeLine = getLineNumber(ScopeLoc);
3622+
llvm::DISubroutineType *DIFnType = getOrCreateFunctionType(D, FnType, Unit);
3623+
llvm::DISubprogram *Decl = nullptr;
3624+
if (D)
3625+
Decl = isa<ObjCMethodDecl>(D)
3626+
? getObjCMethodDeclaration(D, DIFnType, LineNo, Flags, SPFlags)
3627+
: getFunctionDeclaration(D);
35903628

35913629
// FIXME: The function declaration we're constructing here is mostly reusing
35923630
// declarations from CXXMethodDecl and not constructing new ones for arbitrary
35933631
// FunctionDecls. When/if we fix this we can have FDContext be TheCU/null for
35943632
// all subprograms instead of the actual context since subprogram definitions
35953633
// are emitted as CU level entities by the backend.
35963634
llvm::DISubprogram *SP = DBuilder.createFunction(
3597-
FDContext, Name, LinkageName, Unit, LineNo,
3598-
getOrCreateFunctionType(D, FnType, Unit), ScopeLine, FlagsForDef,
3599-
SPFlagsForDef, TParamsArray.get(), getFunctionDeclaration(D));
3635+
FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine,
3636+
FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl);
36003637
Fn->setSubprogram(SP);
36013638
// We might get here with a VarDecl in the case we're generating
36023639
// code for the initialization of globals. Do not record these decls
36033640
// as they will overwrite the actual VarDecl Decl in the cache.
36043641
if (HasDecl && isa<FunctionDecl>(D))
36053642
DeclCache[D->getCanonicalDecl()].reset(SP);
36063643

3607-
if (CGM.getCodeGenOpts().DwarfVersion >= 5) {
3608-
// Starting with DWARF V5 method declarations are emitted as children of
3609-
// the interface type.
3610-
if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) {
3611-
const ObjCInterfaceDecl *ID = OMD->getClassInterface();
3612-
QualType QTy(ID->getTypeForDecl(), 0);
3613-
auto It = TypeCache.find(QTy.getAsOpaquePtr());
3614-
if (It != TypeCache.end()) {
3615-
llvm::DICompositeType *InterfaceDecl =
3616-
cast<llvm::DICompositeType>(It->second);
3617-
llvm::DISubprogram *FD = DBuilder.createFunction(
3618-
InterfaceDecl, Name, LinkageName, Unit, LineNo,
3619-
getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags,
3620-
TParamsArray.get());
3621-
DBuilder.finalizeSubprogram(FD);
3622-
ObjCMethodCache[ID].push_back(FD);
3623-
}
3624-
}
3625-
}
3626-
36273644
// Push the function onto the lexical block stack.
36283645
LexicalBlockStack.emplace_back(SP);
36293646

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,17 @@ class CGDebugInfo {
587587
/// declaration for the given method definition.
588588
llvm::DISubprogram *getFunctionDeclaration(const Decl *D);
589589

590+
/// \return debug info descriptor to the describe method declaration
591+
/// for the given method definition.
592+
/// \param FnType For Objective-C methods, their type.
593+
/// \param LineNo The declaration's line number.
594+
/// \param Flags The DIFlags for the method declaration.
595+
/// \param SPFlags The subprogram-spcific flags for the method declaration.
596+
llvm::DISubprogram *
597+
getObjCMethodDeclaration(const Decl *D, llvm::DISubroutineType *FnType,
598+
unsigned LineNo, llvm::DINode::DIFlags Flags,
599+
llvm::DISubprogram::DISPFlags SPFlags);
600+
590601
/// \return debug info descriptor to describe in-class static data
591602
/// member declaration for the given out-of-class definition. If D
592603
/// is an out-of-class definition of a static data member of a

clang/lib/CodeGen/CGObjC.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -954,8 +954,7 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
954954
const ObjCPropertyImplDecl *PID) {
955955
llvm::Constant *AtomicHelperFn =
956956
CodeGenFunction(CGM).GenerateObjCAtomicGetterCopyHelperFunction(PID);
957-
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
958-
ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
957+
ObjCMethodDecl *OMD = PID->getGetterMethodDecl();
959958
assert(OMD && "Invalid call to generate getter (empty method)");
960959
StartObjCMethod(OMD, IMP->getClassInterface());
961960

@@ -1041,7 +1040,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
10411040

10421041
const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
10431042
QualType propType = prop->getType();
1044-
ObjCMethodDecl *getterMethod = prop->getGetterMethodDecl();
1043+
ObjCMethodDecl *getterMethod = propImpl->getGetterMethodDecl();
10451044

10461045
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
10471046

@@ -1311,9 +1310,8 @@ void
13111310
CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl,
13121311
const ObjCPropertyImplDecl *propImpl,
13131312
llvm::Constant *AtomicHelperFn) {
1314-
const ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
13151313
ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
1316-
ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl();
1314+
ObjCMethodDecl *setterMethod = propImpl->getSetterMethodDecl();
13171315

13181316
// Just use the setter expression if Sema gave us one and it's
13191317
// non-trivial.
@@ -1490,8 +1488,7 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
14901488
const ObjCPropertyImplDecl *PID) {
14911489
llvm::Constant *AtomicHelperFn =
14921490
CodeGenFunction(CGM).GenerateObjCAtomicSetterCopyHelperFunction(PID);
1493-
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
1494-
ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
1491+
ObjCMethodDecl *OMD = PID->getSetterMethodDecl();
14951492
assert(OMD && "Invalid call to generate setter (empty method)");
14961493
StartObjCMethod(OMD, IMP->getClassInterface());
14971494

clang/lib/CodeGen/CGObjCGNU.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,13 +1879,12 @@ class CGObjCGNUstep2 : public CGObjCGNUstep {
18791879
for (auto *propImpl : OID->property_impls())
18801880
if (propImpl->getPropertyImplementation() ==
18811881
ObjCPropertyImplDecl::Synthesize) {
1882-
ObjCPropertyDecl *prop = propImpl->getPropertyDecl();
1883-
auto addIfExists = [&](const ObjCMethodDecl* OMD) {
1884-
if (OMD)
1882+
auto addIfExists = [&](const ObjCMethodDecl *OMD) {
1883+
if (OMD && OMD->hasBody())
18851884
InstanceMethods.push_back(OMD);
18861885
};
1887-
addIfExists(prop->getGetterMethodDecl());
1888-
addIfExists(prop->getSetterMethodDecl());
1886+
addIfExists(propImpl->getGetterMethodDecl());
1887+
addIfExists(propImpl->getSetterMethodDecl());
18891888
}
18901889

18911890
if (InstanceMethods.size() == 0)
@@ -3493,13 +3492,12 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
34933492
for (auto *propertyImpl : OID->property_impls())
34943493
if (propertyImpl->getPropertyImplementation() ==
34953494
ObjCPropertyImplDecl::Synthesize) {
3496-
ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
34973495
auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
34983496
if (accessor)
34993497
InstanceMethods.push_back(accessor);
35003498
};
3501-
addPropertyMethod(property->getGetterMethodDecl());
3502-
addPropertyMethod(property->getSetterMethodDecl());
3499+
addPropertyMethod(propertyImpl->getGetterMethodDecl());
3500+
addPropertyMethod(propertyImpl->getSetterMethodDecl());
35033501
}
35043502

35053503
llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);

0 commit comments

Comments
 (0)