[clang] 2893d55 - [Serialization] Don't warn when a deserialized category is equivalent to an existing one.

Volodymyr Sapsai via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 22 11:07:09 PST 2023


Author: Volodymyr Sapsai
Date: 2023-02-22T11:01:40-08:00
New Revision: 2893d55f8f61edb2c253b960cab1107ea6c163c2

URL: https://github.com/llvm/llvm-project/commit/2893d55f8f61edb2c253b960cab1107ea6c163c2
DIFF: https://github.com/llvm/llvm-project/commit/2893d55f8f61edb2c253b960cab1107ea6c163c2.diff

LOG: [Serialization] Don't warn when a deserialized category is equivalent to an existing one.

A single class allows multiple categories to be defined for it. But if
two of such categories have the same name, we emit a warning. It's not a
hard error but a good indication of a potential mistake.

With modules, we can end up with the same category in different modules.
Diagnosing such a situation has little value as the categories in
different modules are equivalent and don't reflect the usage of the same
name for different purposes. When we deserialize a duplicate category,
compare it to an existing one and warn only when the new one is
different.

rdar://104582081

Differential Revision: https://reviews.llvm.org/D144149

Added: 
    

Modified: 
    clang/lib/Serialization/ASTReaderDecl.cpp
    clang/test/Modules/compare-objc-interface.m
    clang/test/Modules/hidden-duplicates.m
    clang/test/Modules/objc-categories.m

Removed: 
    


################################################################################
diff  --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 8cb513eff13e0..b9bbc0ec9eb28 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -14,6 +14,7 @@
 #include "ASTCommon.h"
 #include "ASTReaderInternals.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTStructuralEquivalence.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/AttrIterator.h"
 #include "clang/AST/Decl.h"
@@ -4181,23 +4182,22 @@ namespace {
       // Check for duplicate categories.
       if (Cat->getDeclName()) {
         ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()];
-        if (Existing &&
-            Reader.getOwningModuleFile(Existing)
-                                          != Reader.getOwningModuleFile(Cat)) {
-          // FIXME: We should not warn for duplicates in diamond:
-          //
-          //   MT     //
-          //  /  \    //
-          // ML  MR   //
-          //  \  /    //
-          //   MB     //
-          //
-          // If there are duplicates in ML/MR, there will be warning when
-          // creating MB *and* when importing MB. We should not warn when
-          // importing.
-          Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def)
-            << Interface->getDeclName() << Cat->getDeclName();
-          Reader.Diag(Existing->getLocation(), diag::note_previous_definition);
+        if (Existing && Reader.getOwningModuleFile(Existing) !=
+                            Reader.getOwningModuleFile(Cat)) {
+          llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
+          StructuralEquivalenceContext Ctx(
+              Cat->getASTContext(), Existing->getASTContext(),
+              NonEquivalentDecls, StructuralEquivalenceKind::Default,
+              /*StrictTypeSpelling =*/false,
+              /*Complain =*/false,
+              /*ErrorOnTagTypeMismatch =*/true);
+          if (!Ctx.IsEquivalent(Cat, Existing)) {
+            // Warn only if the categories with the same name are 
diff erent.
+            Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def)
+                << Interface->getDeclName() << Cat->getDeclName();
+            Reader.Diag(Existing->getLocation(),
+                        diag::note_previous_definition);
+          }
         } else if (!Existing) {
           // Record this category.
           Existing = Cat;

diff  --git a/clang/test/Modules/compare-objc-interface.m b/clang/test/Modules/compare-objc-interface.m
index 17a03de3ce29b..cc3b5fe60b1f5 100644
--- a/clang/test/Modules/compare-objc-interface.m
+++ b/clang/test/Modules/compare-objc-interface.m
@@ -444,3 +444,54 @@ @interface CompareLastImplAttribute: NSObject
 // 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-re at second.h:* {{but in {{'Second'|definition here}} found property 'lastImplAttribute' with 
diff erent 'direct' attribute}}
 #endif
+
+#if defined(FIRST)
+ at interface CompareMatchingCategories: NSObject @end
+ at interface CompareMatchingCategories(Matching)
+- (int)testMethod;
+ at end
+
+ at interface CompareMismatchingCategories1: NSObject @end
+ at interface CompareMismatchingCategories1(Category1)
+- (void)presentMethod;
+ at end
+ at interface CompareMismatchingCategories2: NSObject @end
+ at interface CompareMismatchingCategories2(Category2)
+ at end
+
+ at interface CompareDifferentCategoryNames: NSObject @end
+ at interface CompareDifferentCategoryNames(CategoryFirst)
+- (void)firstMethod:(int)x;
+ at end
+#elif defined(SECOND)
+ at interface CompareMatchingCategories: NSObject @end
+ at interface CompareMatchingCategories(Matching)
+- (int)testMethod;
+ at end
+
+ at interface CompareMismatchingCategories1: NSObject @end
+ at interface CompareMismatchingCategories1(Category1)
+ at end
+ at interface CompareMismatchingCategories2: NSObject @end
+ at interface CompareMismatchingCategories2(Category2)
+- (void)presentMethod;
+ at end
+
+ at interface CompareDifferentCategoryNames: NSObject @end
+ at interface CompareDifferentCategoryNames(CategorySecond)
+- (void)secondMethod;
+ at end
+#else
+CompareMatchingCategories *compareMatchingCategories; // no diagnostic
+CompareMismatchingCategories1 *compareMismatchingCategories1;
+#ifdef TEST_MODULAR
+// expected-warning at second.h:* {{duplicate definition of category 'Category1' on interface 'CompareMismatchingCategories1'}}
+// expected-note at first.h:* {{previous definition is here}}
+#endif
+CompareMismatchingCategories2 *compareMismatchingCategories2;
+#ifdef TEST_MODULAR
+// expected-warning at second.h:* {{duplicate definition of category 'Category2' on interface 'CompareMismatchingCategories2'}}
+// expected-note at first.h:* {{previous definition is here}}
+#endif
+CompareDifferentCategoryNames *compareDifferentCategoryNames; // no diagnostic
+#endif

diff  --git a/clang/test/Modules/hidden-duplicates.m b/clang/test/Modules/hidden-duplicates.m
index b3af9697cc0b8..62c49424d1fc4 100644
--- a/clang/test/Modules/hidden-duplicates.m
+++ b/clang/test/Modules/hidden-duplicates.m
@@ -32,6 +32,7 @@ @protocol ForwardDeclaredProtocolWithoutDefinition;
 
 @interface NSObject @end
 @class ForwardDeclaredInterfaceWithoutDefinition;
+ at interface NSObject(CategoryForTesting) @end
 
 NSObject *interfaceDefinition(NSObject *o);
 NSObject *forwardDeclaredInterface(NSObject *o);

diff  --git a/clang/test/Modules/objc-categories.m b/clang/test/Modules/objc-categories.m
index fcffe3cc96200..8bc73a29c51cb 100644
--- a/clang/test/Modules/objc-categories.m
+++ b/clang/test/Modules/objc-categories.m
@@ -8,8 +8,6 @@
 
 @import category_bottom;
 
-// expected-note at Inputs/category_left.h:14 {{previous definition}}
-// expected-warning at Inputs/category_right.h:12 {{duplicate definition of category}}
 // expected-note at Inputs/category_top.h:1 {{receiver is instance of class declared here}}
 
 @interface Foo(Source)


        


More information about the cfe-commits mailing list