Skip to content

Commit d9eca33

Browse files
committed
[modules] Fix tracking ObjCInterfaceType decl when there are multiple definitions.
With the old approach we were updating `ObjCInterfaceType.Decl` to the last encountered definition. But during loading modules `ASTDeclReader::VisitObjCInterfaceDecl` keeps the *first* encountered definition. So with multiple definitions imported there would be a disagreement between expected definition in `ObjCInterfaceType.Decl` and actual definition `ObjCInterfaceDecl::getDefinition` which can lead to incorrect diagnostic. Fix by not tracking definition in `ObjCInterfaceType` explicitly but by getting it from redeclaration chain. Partially reverted 919fc50 keeping the modified test case as the correct behavior is achieved in a different way. Differential Revision: https://reviews.llvm.org/D110452
1 parent 52f4922 commit d9eca33

File tree

6 files changed

+26
-19
lines changed

6 files changed

+26
-19
lines changed

clang/include/clang/AST/Type.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6016,18 +6016,17 @@ inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() {
60166016
class ObjCInterfaceType : public ObjCObjectType {
60176017
friend class ASTContext; // ASTContext creates these.
60186018
friend class ASTReader;
6019-
friend class ObjCInterfaceDecl;
60206019
template <class T> friend class serialization::AbstractTypeReader;
60216020

6022-
mutable ObjCInterfaceDecl *Decl;
6021+
ObjCInterfaceDecl *Decl;
60236022

60246023
ObjCInterfaceType(const ObjCInterfaceDecl *D)
60256024
: ObjCObjectType(Nonce_ObjCInterface),
60266025
Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
60276026

60286027
public:
60296028
/// Get the declaration of this interface.
6030-
ObjCInterfaceDecl *getDecl() const { return Decl; }
6029+
ObjCInterfaceDecl *getDecl() const;
60316030

60326031
bool isSugared() const { return false; }
60336032
QualType desugar() const { return QualType(this, 0); }

clang/lib/AST/DeclObjC.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -603,10 +603,6 @@ void ObjCInterfaceDecl::allocateDefinitionData() {
603603
assert(!hasDefinition() && "ObjC class already has a definition");
604604
Data.setPointer(new (getASTContext()) DefinitionData());
605605
Data.getPointer()->Definition = this;
606-
607-
// Make the type point at the definition, now that we have one.
608-
if (TypeForDecl)
609-
cast<ObjCInterfaceType>(TypeForDecl)->Decl = this;
610606
}
611607

612608
void ObjCInterfaceDecl::startDefinition() {

clang/lib/AST/Type.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,13 @@ QualType ObjCObjectType::stripObjCKindOfTypeAndQuals(
821821
/*isKindOf=*/false);
822822
}
823823

824+
ObjCInterfaceDecl *ObjCInterfaceType::getDecl() const {
825+
ObjCInterfaceDecl *Canon = Decl->getCanonicalDecl();
826+
if (ObjCInterfaceDecl *Def = Canon->getDefinition())
827+
return Def;
828+
return Canon;
829+
}
830+
824831
const ObjCObjectPointerType *ObjCObjectPointerType::stripObjCKindOfTypeAndQuals(
825832
const ASTContext &ctx) const {
826833
if (!isKindOfType() && qual_empty())

clang/lib/Sema/SemaLookup.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5323,11 +5323,8 @@ static NamedDecl *getDefinitionToImport(NamedDecl *D) {
53235323
return FD->getDefinition();
53245324
if (TagDecl *TD = dyn_cast<TagDecl>(D))
53255325
return TD->getDefinition();
5326-
// The first definition for this ObjCInterfaceDecl might be in the TU
5327-
// and not associated with any module. Use the one we know to be complete
5328-
// and have just seen in a module.
53295326
if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
5330-
return ID;
5327+
return ID->getDefinition();
53315328
if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
53325329
return PD->getDefinition();
53335330
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))

clang/test/Modules/decldef.mm

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// RUN: rm -rf %t
2-
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_1 -DUSE_2 -DUSE_3 -DUSE_4
3-
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_2 -DUSE_3 -DUSE_4
4-
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_3 -DUSE_4
5-
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_4
2+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_1 -DUSE_2 -DUSE_3 -DUSE_4 -DUSE_5
3+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_2 -DUSE_3 -DUSE_4 -DUSE_5
4+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_3 -DUSE_4 -DUSE_5
5+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_4 -DUSE_5
6+
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_5
67

78
// expected-note@Inputs/def.h:5 0-1{{here}}
9+
// expected-note@Inputs/def.h:11 0-1{{here}}
810
// expected-note@Inputs/def.h:16 0-1{{here}}
911
// expected-note@Inputs/def-include.h:11 0-1{{here}}
1012

@@ -51,11 +53,17 @@ void testB() {
5153
}
5254

5355
void testDef() {
56+
#ifdef USE_4
5457
[def defMethod];
58+
#ifndef USED
59+
// expected-error@-2{{definition of 'Def' must be imported from module 'decldef.Def' before it is required}}
60+
#define USED
61+
#endif
62+
#endif
5563
}
5664

5765
void testDef2() {
58-
#ifdef USE_4
66+
#ifdef USE_5
5967
def2->func();
6068
def3->func();
6169
#ifndef USED
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// RUN: rm -rf %t
22
// RUN: %clang_cc1 %s -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/interface-diagnose-missing-import -verify
3+
// expected-no-diagnostics
34
@interface Buggy
45
@end
56

67
@import Foo.Bar;
78

8-
@interface Buggy (MyExt) // expected-error {{definition of 'Buggy' must be imported from module 'Foo' before it is required}}
9+
// No diagnostic for inaccessible 'Buggy' definition because we have another definition right in this file.
10+
@interface Buggy (MyExt)
911
@end
10-
11-
// expected-note@Foo/RandoPriv.h:3{{definition here is not reachable}}

0 commit comments

Comments
 (0)