[clang] ed7a46a - [modules] Allow parsing a duplicate Obj-C interface if a previous one comes from a hidden [sub]module.
Volodymyr Sapsai via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 20 08:18:28 PST 2023
Author: Volodymyr Sapsai
Date: 2023-01-20T10:18:18-06:00
New Revision: ed7a46a8de77087447936965044e2faf734102e5
URL: https://github.com/llvm/llvm-project/commit/ed7a46a8de77087447936965044e2faf734102e5
DIFF: https://github.com/llvm/llvm-project/commit/ed7a46a8de77087447936965044e2faf734102e5.diff
LOG: [modules] Allow parsing a duplicate Obj-C interface if a previous one comes from a hidden [sub]module.
Instead of emitting a redefinition error, check that definitions are
equivalent and allow such scenario.
A few non-obvious implementation details:
* to avoid multiple definitions in the redeclaration chain we just drop
the new definition after checking for equivalence;
* for checking definition equivalence use ODR hash instead of
ASTStructuralEquivalence because it avoids excessive recursive
deserialization. Though after detecting a mismatch we do deserialize
multiple entities to provide a better error message.
rdar://82908223
Differential Revision: https://reviews.llvm.org/D124286
Added:
Modified:
clang/include/clang/AST/DeclObjC.h
clang/include/clang/AST/ODRDiagsEmitter.h
clang/include/clang/Basic/DiagnosticASTKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/AST/DeclObjC.cpp
clang/lib/AST/ODRDiagsEmitter.cpp
clang/lib/Parse/ParseObjc.cpp
clang/lib/Sema/SemaDeclObjC.cpp
clang/test/Modules/compare-objc-interface.m
clang/test/Modules/hidden-duplicates.m
Removed:
################################################################################
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index 77fde99b6b60b..3d650b82f2b9b 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -1542,6 +1542,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// a forward declaration (\@class) to a definition (\@interface).
void startDefinition();
+ /// Starts the definition without sharing it with other redeclarations.
+ /// Such definition shouldn't be used for anything but only to compare if
+ /// a duplicate is compatible with previous definition or if it is
+ /// a distinct duplicate.
+ void startDuplicateDefinitionForComparison();
+ void mergeDuplicateDefinitionWithCommon(const ObjCInterfaceDecl *Definition);
+
/// Retrieve the superclass type.
const ObjCObjectType *getSuperClassType() const {
if (TypeSourceInfo *TInfo = getSuperClassTInfo())
diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h
index fdbd85cb10e5b..1f7faaa06e540 100644
--- a/clang/include/clang/AST/ODRDiagsEmitter.h
+++ b/clang/include/clang/AST/ODRDiagsEmitter.h
@@ -58,6 +58,15 @@ class ODRDiagsEmitter {
const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID,
const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const;
+ /// Diagnose ODR mismatch between ObjCInterfaceDecl with
diff erent
+ /// definitions.
+ bool diagnoseMismatch(const ObjCInterfaceDecl *FirstID,
+ const ObjCInterfaceDecl *SecondID) const {
+ assert(FirstID->data().Definition != SecondID->data().Definition &&
+ "Don't diagnose
diff erences when definitions are merged already");
+ return diagnoseMismatch(FirstID, SecondID, &SecondID->data());
+ }
+
/// Diagnose ODR mismatch between 2 ObjCProtocolDecl.
///
/// Returns true if found a mismatch and diagnosed it.
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 715249b9d6f5e..28120d13fd9e7 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -624,12 +624,12 @@ def err_module_odr_violation_objc_interface : Error <
"%select{|@private|@protected|@public|@package}5"
"}3">;
def note_module_odr_violation_objc_interface : Note <
- "but in '%0' found "
+ "but in %select{'%1'|definition here}0 found "
"%select{"
- "%select{no super class|super class with type %3}2|"
- "instance variable '%2' access control is "
- "%select{|@private|@protected|@public|@package}3"
- "}1">;
+ "%select{no super class|super class with type %4}3|"
+ "instance variable '%3' access control is "
+ "%select{|@private|@protected|@public|@package}4"
+ "}2">;
def err_module_odr_violation_template_parameter : Error <
"%q0 has
diff erent definitions in
diff erent modules; first
diff erence is "
@@ -778,16 +778,17 @@ def err_module_odr_violation_field : Error<
"field %4 with %select{no|an}5 initalizer|"
"field %4 with an initializer"
"}3">;
-def note_module_odr_violation_field : Note<"but in '%0' found "
+def note_module_odr_violation_field : Note<
+ "but in %select{'%1'|definition here}0 found "
"%select{"
- "field %2|"
- "field %2 with type %3|"
- "%select{non-|}3bitfield %2|"
- "bitfield %2 with
diff erent width expression|"
- "%select{non-|}3mutable field %2|"
- "field %2 with %select{no|an}3 initializer|"
- "field %2 with a
diff erent initializer"
- "}1">;
+ "field %3|"
+ "field %3 with type %4|"
+ "%select{non-|}4bitfield %3|"
+ "bitfield %3 with
diff erent width expression|"
+ "%select{non-|}4mutable field %3|"
+ "field %3 with %select{no|an}4 initializer|"
+ "field %3 with a
diff erent initializer"
+ "}2">;
def err_module_odr_violation_typedef : Error<
"%q0 has
diff erent definitions in
diff erent modules; first
diff erence is "
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e504111fce059..0891dd0e0dd87 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10186,7 +10186,7 @@ class Sema final {
ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,
Decl *const *ProtoRefs, unsigned NumProtoRefs,
const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
- const ParsedAttributesView &AttrList);
+ const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody);
void ActOnSuperClassOfClassInterface(Scope *S,
SourceLocation AtInterfaceLoc,
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index 33b9d33075a2a..e934a81d086e3 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -624,6 +624,17 @@ void ObjCInterfaceDecl::startDefinition() {
}
}
+void ObjCInterfaceDecl::startDuplicateDefinitionForComparison() {
+ Data.setPointer(nullptr);
+ allocateDefinitionData();
+ // Don't propagate data to other redeclarations.
+}
+
+void ObjCInterfaceDecl::mergeDuplicateDefinitionWithCommon(
+ const ObjCInterfaceDecl *Definition) {
+ Data = Definition->Data;
+}
+
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
ObjCInterfaceDecl *&clsDeclared) {
// FIXME: Should make sure no callers ever do this.
diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp b/clang/lib/AST/ODRDiagsEmitter.cpp
index bd23fda6ac921..b3fe070889c5f 100644
--- a/clang/lib/AST/ODRDiagsEmitter.cpp
+++ b/clang/lib/AST/ODRDiagsEmitter.cpp
@@ -164,7 +164,7 @@ bool ODRDiagsEmitter::diagnoseSubMismatchField(
this](ODRFieldDifference DiffType) {
return Diag(SecondField->getLocation(),
diag::note_module_odr_violation_field)
- << SecondModule << SecondField->getSourceRange() << DiffType;
+ << SecondModule.empty() << SecondModule << SecondField->getSourceRange() << DiffType;
};
IdentifierInfo *FirstII = FirstField->getIdentifier();
@@ -175,9 +175,6 @@ bool ODRDiagsEmitter::diagnoseSubMismatchField(
return true;
}
- assert(Context.hasSameType(FirstField->getType(), SecondField->getType()));
- (void)Context;
-
QualType FirstType = FirstField->getType();
QualType SecondType = SecondField->getType();
if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
@@ -186,6 +183,9 @@ bool ODRDiagsEmitter::diagnoseSubMismatchField(
return true;
}
+ assert(Context.hasSameType(FirstField->getType(), SecondField->getType()));
+ (void)Context;
+
const bool IsFirstBitField = FirstField->isBitField();
const bool IsSecondBitField = SecondField->isBitField();
if (IsFirstBitField != IsSecondBitField) {
@@ -1941,7 +1941,7 @@ bool ODRDiagsEmitter::diagnoseMismatch(
auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
ODRInterfaceDifference DiffType) {
return Diag(Loc, diag::note_module_odr_violation_objc_interface)
- << SecondModule << Range << DiffType;
+ << SecondModule.empty() << SecondModule << Range << DiffType;
};
const struct ObjCInterfaceDecl::DefinitionData *FirstDD = &FirstID->data();
@@ -2007,8 +2007,10 @@ bool ODRDiagsEmitter::diagnoseMismatch(
DeclHashes FirstHashes;
DeclHashes SecondHashes;
- PopulateHashes(FirstHashes, FirstID, FirstID);
- PopulateHashes(SecondHashes, SecondID, FirstID);
+ // Use definition as DeclContext because definitions are merged when
+ // DeclContexts are merged and separate when DeclContexts are separate.
+ PopulateHashes(FirstHashes, FirstID, FirstID->getDefinition());
+ PopulateHashes(SecondHashes, SecondID, SecondID->getDefinition());
DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 4a18cce11febc..079bf9a9c08cc 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -370,17 +370,30 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
Actions.ActOnTypedefedProtocols(protocols, protocolLocs,
superClassId, superClassLoc);
+ Sema::SkipBodyInfo SkipBody;
ObjCInterfaceDecl *ClsType = Actions.ActOnStartClassInterface(
getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId,
superClassLoc, typeArgs,
SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(),
- protocols.size(), protocolLocs.data(), EndProtoLoc, attrs);
+ protocols.size(), protocolLocs.data(), EndProtoLoc, attrs, &SkipBody);
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);
ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);
+ if (SkipBody.CheckSameAsPrevious) {
+ auto *PreviousDef = cast<ObjCInterfaceDecl>(SkipBody.Previous);
+ if (Actions.ActOnDuplicateODRHashDefinition(ClsType, PreviousDef)) {
+ ClsType->mergeDuplicateDefinitionWithCommon(PreviousDef->getDefinition());
+ } else {
+ ODRDiagsEmitter DiagsEmitter(Diags, Actions.getASTContext(),
+ getPreprocessor().getLangOpts());
+ DiagsEmitter.diagnoseMismatch(PreviousDef, ClsType);
+ ClsType->setInvalidDecl();
+ }
+ }
+
return ClsType;
}
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index a7443f736e363..fdfc6d312b387 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -978,7 +978,7 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface(
ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,
Decl *const *ProtoRefs, unsigned NumProtoRefs,
const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
- const ParsedAttributesView &AttrList) {
+ const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) {
assert(ClassName && "Missing class identifier");
// Check for another declaration kind with the same name.
@@ -1057,10 +1057,16 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface(
if (PrevIDecl) {
// Class already seen. Was it a definition?
if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
- Diag(AtInterfaceLoc, diag::err_duplicate_class_def)
- << PrevIDecl->getDeclName();
- Diag(Def->getLocation(), diag::note_previous_definition);
- IDecl->setInvalidDecl();
+ if (SkipBody && !hasVisibleDefinition(Def)) {
+ SkipBody->CheckSameAsPrevious = true;
+ SkipBody->New = IDecl;
+ SkipBody->Previous = Def;
+ } else {
+ Diag(AtInterfaceLoc, diag::err_duplicate_class_def)
+ << PrevIDecl->getDeclName();
+ Diag(Def->getLocation(), diag::note_previous_definition);
+ IDecl->setInvalidDecl();
+ }
}
}
@@ -1075,7 +1081,9 @@ ObjCInterfaceDecl *Sema::ActOnStartClassInterface(
// Start the definition of this class. If we're in a redefinition case, there
// may already be a definition, so we'll end up adding to it.
- if (!IDecl->hasDefinition())
+ if (SkipBody && SkipBody->CheckSameAsPrevious)
+ IDecl->startDuplicateDefinitionForComparison();
+ else if (!IDecl->hasDefinition())
IDecl->startDefinition();
if (SuperName) {
diff --git a/clang/test/Modules/compare-objc-interface.m b/clang/test/Modules/compare-objc-interface.m
index 71f1cc853a7a3..17a03de3ce29b 100644
--- a/clang/test/Modules/compare-objc-interface.m
+++ b/clang/test/Modules/compare-objc-interface.m
@@ -19,6 +19,11 @@
// RUN: %clang_cc1 -I%t/include -verify %t/test.m -fblocks -fobjc-arc \
// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache
+// Run the same test with second.h being modular
+// RUN: cat %t/include/second.modulemap >> %t/include/module.modulemap
+// RUN: %clang_cc1 -I%t/include -verify %t/test.m -fblocks -fobjc-arc -DTEST_MODULAR=1 \
+// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache
+
// Test that we don't accept
diff erent class definitions with the same name
// from multiple modules but detect mismatches and provide actionable
// diagnostic.
@@ -42,6 +47,8 @@ @protocol ExtraProtocol @end
export *
}
}
+
+//--- include/second.modulemap
module Second {
header "second.h"
export *
@@ -87,13 +94,13 @@ @interface CompareDifferentSuperclass: DifferentSuperclass @end
CompareMatchingSuperclass *compareMatchingSuperclass;
CompareSuperclassPresence1 *compareSuperclassPresence1;
// expected-error at first.h:* {{'CompareSuperclassPresence1' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found super class with type 'NSObject'}}
-// expected-note at second.h:* {{but in 'Second' found no super class}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found no super class}}
CompareSuperclassPresence2 *compareSuperclassPresence2;
// expected-error at first.h:* {{'CompareSuperclassPresence2' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found no super class}}
-// expected-note at second.h:* {{but in 'Second' found super class with type 'NSObject'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found super class with type 'NSObject'}}
CompareDifferentSuperclass *compareDifferentSuperclass;
// expected-error at first.h:* {{'CompareDifferentSuperclass' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found super class with type 'NSObject'}}
-// expected-note at second.h:* {{but in 'Second' found super class with type 'DifferentSuperclass'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found super class with type 'DifferentSuperclass'}}
#endif
#if defined(FIRST)
@@ -122,17 +129,17 @@ @interface CompareProtocolOrder: NSObject<ExtraProtocol, CommonProtocol> @end
CompareProtocolPresence1 *compareProtocolPresence1;
// expected-error at first.h:* {{'CompareProtocolPresence1' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found 1 referenced protocol}}
-// expected-note at second.h:* {{but in 'Second' found 0 referenced protocols}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found 0 referenced protocols}}
CompareProtocolPresence2 *compareProtocolPresence2;
// expected-error at first.h:* {{'CompareProtocolPresence2' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found 0 referenced protocols}}
-// expected-note at second.h:* {{but in 'Second' found 1 referenced protocol}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found 1 referenced protocol}}
CompareDifferentProtocols *compareDifferentProtocols;
// expected-error at first.h:* {{'CompareDifferentProtocols' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found 1st referenced protocol with name 'CommonProtocol'}}
-// expected-note at second.h:* {{but in 'Second' found 1st referenced protocol with
diff erent name 'ExtraProtocol'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found 1st referenced protocol with
diff erent name 'ExtraProtocol'}}
CompareProtocolOrder *compareProtocolOrder;
// expected-error at first.h:* {{'CompareProtocolOrder' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found 1st referenced protocol with name 'CommonProtocol'}}
-// expected-note at second.h:* {{but in 'Second' found 1st referenced protocol with
diff erent name 'ExtraProtocol'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found 1st referenced protocol with
diff erent name 'ExtraProtocol'}}
#endif
#if defined(FIRST)
@@ -186,28 +193,43 @@ @interface CompareIVarVisibilityDefault: NSObject {
CompareMatchingIVars *compareMatchingIVars;
CompareIVarPresence1 *compareIVarPresence1;
+#ifdef TEST_MODULAR
// expected-error at second.h:* {{'CompareIVarPresence1::ivarPresence1' from module 'Second' is not present in definition of 'CompareIVarPresence1' in module 'First.Hidden'}}
// expected-note at first.h:* {{definition has no member 'ivarPresence1'}}
+#else
+// expected-error at first.h:* {{'CompareIVarPresence1' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found end of class}}
+// expected-note at second.h:* {{but in definition here found instance variable}}
+#endif
CompareIVarPresence2 *compareIVarPresence2;
// expected-error at first.h:* {{'CompareIVarPresence2' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found instance variable}}
-// expected-note at second.h:* {{but in 'Second' found end of class}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found end of class}}
CompareIVarName *compareIVarName;
+#ifdef TEST_MODULAR
// expected-error at second.h:* {{'CompareIVarName::
diff erentIvarName' from module 'Second' is not present in definition of 'CompareIVarName' in module 'First.Hidden'}}
// expected-note at first.h:* {{definition has no member '
diff erentIvarName'}}
+#else
+// expected-error at first.h:* {{'CompareIVarName' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found field 'ivarName'}}
+// expected-note at second.h:* {{but in definition here found field '
diff erentIvarName'}}
+#endif
CompareIVarType *compareIVarType;
+#ifdef TEST_MODULAR
// expected-error at second.h:* {{'CompareIVarType::ivarType' from module 'Second' is not present in definition of 'CompareIVarType' in module 'First.Hidden'}}
// expected-note at first.h:* {{declaration of 'ivarType' does not match}}
+#else
+// expected-error at first.h:* {{'CompareIVarType' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found field 'ivarType' with type 'int'}}
+// expected-note at second.h:* {{but in definition here found field 'ivarType' with type 'float'}}
+#endif
CompareIVarOrder *compareIVarOrder;
// expected-error at first.h:* {{'CompareIVarOrder' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found field 'ivarNameInt'}}
-// expected-note at second.h:* {{but in 'Second' found field 'ivarNameFloat'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found field 'ivarNameFloat'}}
CompareIVarVisibilityExplicit *compareIVarVisibilityExplicit;
// expected-error at first.h:* {{'CompareIVarVisibilityExplicit' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found instance variable 'ivarVisibility' access control is @public}}
-// expected-note at second.h:* {{but in 'Second' found instance variable 'ivarVisibility' access control is @private}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found instance variable 'ivarVisibility' access control is @private}}
CompareIVarVisibilityDefault *compareIVarVisibilityDefault;
// expected-error at first.h:* {{'CompareIVarVisibilityDefault' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found instance variable 'ivarVisibilityDefault' access control is @protected}}
-// expected-note at second.h:* {{but in 'Second' found instance variable 'ivarVisibilityDefault' access control is @public}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found instance variable 'ivarVisibilityDefault' access control is @public}}
#endif
#if defined(FIRST)
@@ -288,34 +310,34 @@ - (void)methodClassInstance;
CompareMatchingMethods *compareMatchingMethods;
CompareMethodPresence1 *compareMethodPresence1;
// expected-error at first.h:* {{'CompareMethodPresence1' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found method}}
-// expected-note at second.h:* {{but in 'Second' found end of class}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found end of class}}
CompareMethodPresence2 *compareMethodPresence2;
// expected-error at first.h:* {{'CompareMethodPresence2' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found end of class}}
-// expected-note at second.h:* {{but in 'Second' found method}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found method}}
CompareMethodName *compareMethodName;
// expected-error at first.h:* {{'CompareMethodName' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found method 'methodNameA'}}
-// expected-note at second.h:* {{but in 'Second' found
diff erent method 'methodNameB'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found
diff erent method 'methodNameB'}}
CompareMethodArgCount *compareMethodArgCount;
// expected-error at first.h:* {{'CompareMethodArgCount' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found method 'methodArgCount::' that has 2 parameters}}
-// expected-note at second.h:* {{but in 'Second' found method 'methodArgCount:' that has 1 parameter}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found method 'methodArgCount:' that has 1 parameter}}
CompareMethodArgName *compareMethodArgName;
// expected-error at first.h:* {{'CompareMethodArgName' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found method 'methodArgName:' with 1st parameter named 'argNameA'}}
-// expected-note at second.h:* {{but in 'Second' found method 'methodArgName:' with 1st parameter named 'argNameB'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found method 'methodArgName:' with 1st parameter named 'argNameB'}}
CompareMethodArgType *compareMethodArgType;
// expected-error at first.h:* {{'CompareMethodArgType' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found method 'methodArgType:' with 1st parameter of type 'int'}}
-// expected-note at second.h:* {{but in 'Second' found method 'methodArgType:' with 1st parameter of type 'float'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found method 'methodArgType:' with 1st parameter of type 'float'}}
CompareMethodReturnType *compareMethodReturnType;
// expected-error at first.h:* {{'CompareMethodReturnType' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found method 'methodReturnType' with return type 'int'}}
-// expected-note at second.h:* {{but in 'Second' found method 'methodReturnType' with
diff erent return type 'float'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found method 'methodReturnType' with
diff erent return type 'float'}}
CompareMethodOrder *compareMethodOrder;
// expected-error at first.h:* {{'CompareMethodOrder' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found method 'methodOrderFirst'}}
-// expected-note at second.h:* {{but in 'Second' found
diff erent method 'methodOrderSecond'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found
diff erent method 'methodOrderSecond'}}
CompareMethodClassInstance *compareMethodClassInstance;
// expected-error at first.h:* {{'CompareMethodClassInstance' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found class method 'methodClassInstance'}}
-// expected-note at second.h:* {{but in 'Second' found method 'methodClassInstance' as instance method}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found method 'methodClassInstance' as instance method}}
#endif
#if defined(FIRST)
@@ -396,29 +418,29 @@ @interface CompareLastImplAttribute: NSObject
CompareMatchingProperties *compareMatchingProperties;
ComparePropertyPresence1 *comparePropertyPresence1;
// expected-error at first.h:* {{'ComparePropertyPresence1' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found property}}
-// expected-note at second.h:* {{but in 'Second' found end of class}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found end of class}}
ComparePropertyPresence2 *comparePropertyPresence2;
// expected-error at first.h:* {{'ComparePropertyPresence2' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found end of class}}
-// expected-note at second.h:* {{but in 'Second' found property}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found property}}
ComparePropertyName *comparePropertyName;
// expected-error at first.h:* {{'ComparePropertyName' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found property 'propNameA'}}
-// expected-note at second.h:* {{but in 'Second' found property 'propNameB'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found property 'propNameB'}}
ComparePropertyType *comparePropertyType;
// expected-error at first.h:* {{'ComparePropertyType' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found property 'propType' with type 'int'}}
-// expected-note at second.h:* {{but in 'Second' found property 'propType' with type 'float'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found property 'propType' with type 'float'}}
ComparePropertyOrder *comparePropertyOrder;
// expected-error at first.h:* {{'ComparePropertyOrder' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found property 'propOrderX'}}
-// expected-note at second.h:* {{but in 'Second' found property 'propOrderY'}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found property 'propOrderY'}}
CompareMatchingPropertyAttributes *compareMatchingPropertyAttributes;
ComparePropertyAttributes *comparePropertyAttributes;
// expected-error at first.h:* {{'ComparePropertyAttributes' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found property 'propAttributes' with 'readonly' attribute}}
-// expected-note at second.h:* {{but in 'Second' found property 'propAttributes' with
diff erent 'readonly' attribute}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found property 'propAttributes' with
diff erent 'readonly' attribute}}
CompareFirstImplAttribute *compareFirstImplAttribute;
// expected-error at first.h:* {{'CompareFirstImplAttribute' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found property 'firstImplAttribute' with default 'readonly' attribute}}
-// expected-note at second.h:* {{but in 'Second' found property 'firstImplAttribute' with
diff erent 'readonly' attribute}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found property 'firstImplAttribute' with
diff erent 'readonly' attribute}}
CompareLastImplAttribute *compareLastImplAttribute;
// expected-error at first.h:* {{'CompareLastImplAttribute' has
diff erent definitions in
diff erent modules; first
diff erence is definition in module 'First.Hidden' found property 'lastImplAttribute' with 'direct' attribute}}
-// expected-note at second.h:* {{but in 'Second' found property 'lastImplAttribute' with
diff erent 'direct' attribute}}
+// expected-note-re at second.h:* {{but in {{'Second'|definition here}} found property 'lastImplAttribute' with
diff erent 'direct' attribute}}
#endif
diff --git a/clang/test/Modules/hidden-duplicates.m b/clang/test/Modules/hidden-duplicates.m
index 423654502fd81..b3af9697cc0b8 100644
--- a/clang/test/Modules/hidden-duplicates.m
+++ b/clang/test/Modules/hidden-duplicates.m
@@ -30,6 +30,12 @@ @protocol ForwardDeclaredProtocolWithoutDefinition;
id<ForwardDeclaredProtocolWithoutDefinition> forwardDeclaredProtocol(
id<ForwardDeclaredProtocolWithoutDefinition> t);
+ at interface NSObject @end
+ at class ForwardDeclaredInterfaceWithoutDefinition;
+
+NSObject *interfaceDefinition(NSObject *o);
+NSObject *forwardDeclaredInterface(NSObject *o);
+
#endif
//--- include/empty.h
More information about the cfe-commits
mailing list