]> granicus.if.org Git - clang/commitdiff
Fix <rdar://problem/6261178> clang-on-xcode: [sema] multiple method warning is over...
authorSteve Naroff <snaroff@apple.com>
Tue, 21 Oct 2008 10:37:50 +0000 (10:37 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 21 Oct 2008 10:37:50 +0000 (10:37 +0000)
Fix <rdar://problem/6265257> warnings for ambiguous message send swamp other warnings.

Reworked Sema::MatchTwoMethodDeclarations() to optionally match based on method size and alignment (the default in GCC). Changed Sema::LookupInstanceMethodInGlobalPool() to use this feature.

Added -Wno-struct-selector-match to driver, however didn't hook it up yet. Added a FIXME that says this.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57898 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/clang.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/method-lookup-3.m

index fcd4d5ab72421b5d614f66e57e164bd77fa2d4b6..c2afe5b622082e42e873e74ffd4fbfe0b21565a5 100644 (file)
@@ -595,6 +595,11 @@ static llvm::cl::opt<bool>
 WarnImplicitFunctionDeclaration("Wimplicit-function-declaration",
    llvm::cl::desc("Warn about uses of implicitly defined functions"));
 
+static llvm::cl::opt<bool>
+WarnNoStrictSelectorMatch("Wno-strict-selector-match",
+   llvm::cl::desc("Do not warn about duplicate methods that have the same size and alignment"),
+   llvm::cl::init(true));
+
 /// InitializeDiagnostics - Initialize the diagnostic object, based on the
 /// current command line option settings.
 static void InitializeDiagnostics(Diagnostic &Diags) {
index e9e1ad15689078f87c3f81d48dc841c655d0346f..796ba4ed0416ec7a45d664fb1928a03cdb0d432f 100644 (file)
@@ -411,7 +411,8 @@ private:
   /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
   /// true, or false, accordingly.
   bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, 
-                                  const ObjCMethodDecl *PrevMethod); 
+                                  const ObjCMethodDecl *PrevMethod,
+                                  bool matchBasedOnSizeAndAlignment = false); 
 
   /// AddInstanceMethodToGlobalPool - All instance methods in a translation
   /// unit are added to a global pool. This allows us to efficiently associate
index 6375d91448b27eb98777ea1bda4fc6a028f97ff2..d5fa8848c304cc20378d8eb1f38414bf6c3b5e6f 100644 (file)
@@ -739,17 +739,37 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
 /// returns true, or false, accordingly.
 /// TODO: Handle protocol list; such as id<p1,p2> in type comparisons
 bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, 
-                                      const ObjCMethodDecl *PrevMethod) {
-  if (Context.getCanonicalType(Method->getResultType()) !=
-      Context.getCanonicalType(PrevMethod->getResultType()))
-    return false;
-  for (unsigned i = 0, e = Method->getNumParams(); i != e; ++i) {
-    ParmVarDecl *ParamDecl = Method->getParamDecl(i);
-    ParmVarDecl *PrevParamDecl = PrevMethod->getParamDecl(i);
-    if (Context.getCanonicalType(ParamDecl->getType()) !=
-        Context.getCanonicalType(PrevParamDecl->getType()))
+                                      const ObjCMethodDecl *PrevMethod,
+                                      bool matchBasedOnSizeAndAlignment) {
+  QualType T1 = Context.getCanonicalType(Method->getResultType());
+  QualType T2 = Context.getCanonicalType(PrevMethod->getResultType());
+  
+  if (T1 != T2) {
+    // The result types are different.
+    if (!matchBasedOnSizeAndAlignment)
+      return false;
+    // Incomplete types don't have a size and alignment.
+    if (T1->isIncompleteType() || T2->isIncompleteType())
+      return false;
+    // Check is based on size and alignment.
+    if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2))
       return false;
   }
+  for (unsigned i = 0, e = Method->getNumParams(); i != e; ++i) {
+    T1 = Context.getCanonicalType(Method->getParamDecl(i)->getType());
+    T2 = Context.getCanonicalType(PrevMethod->getParamDecl(i)->getType());
+    if (T1 != T2) {
+      // The result types are different.
+      if (!matchBasedOnSizeAndAlignment)
+        return false;
+      // Incomplete types don't have a size and alignment.
+      if (T1->isIncompleteType() || T2->isIncompleteType())
+        return false;
+      // Check is based on size and alignment.
+      if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2))
+        return false;
+    }
+  }
   return true;
 }
 
@@ -776,11 +796,19 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
   }
 }
 
+// FIXME: Finish implementing -Wno-struct-selector-match.
 ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel, 
                                                        SourceRange R) {
   ObjCMethodList &MethList = InstanceMethodPool[Sel];
+  bool issueWarning = false;
   
   if (MethList.Method && MethList.Next) {
+    for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+      // This checks if the methods differ by size & alignment.
+      if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
+        issueWarning = true;
+  }
+  if (issueWarning && (MethList.Method && MethList.Next)) {
     Diag(R.getBegin(), diag::warn_multiple_method_decl, Sel.getName(), R);
     Diag(MethList.Method->getLocStart(), diag::warn_using_decl, 
          MethList.Method->getSourceRange());
index a1815fa386e2c4009ece09f274054f61d7be1224..25299ca6d3bdeea29e8fdb7a217c668099f60a2a 100644 (file)
@@ -22,9 +22,9 @@ typedef struct { int x; } Alternate;
 -(void) x; // expected-warning{{also found}}
 -(void) y; // expected-warning{{also found}}
 -(void) z; // expected-warning{{also found}}
--(void) setX: (INTERFERE_TYPE) arg; // expected-warning{{also found}}
--(void) setY: (INTERFERE_TYPE) arg; // expected-warning{{also found}}
--(void) setZ: (INTERFERE_TYPE) arg; // expected-warning{{also found}}
+-(void) setX: (INTERFERE_TYPE) arg; 
+-(void) setY: (INTERFERE_TYPE) arg;
+-(void) setZ: (INTERFERE_TYPE) arg;
 @end
 
 void f0(id a0) {
@@ -40,13 +40,13 @@ void f2(id a0) {
 }
 
 void f3(id a0, Abstract *a1) { 
-  [ a0 setX: a1]; // expected-warning {{multiple methods named 'setX:' found}}
+  [ a0 setX: a1];
 }
 
 void f4(id a0, Abstract *a1) { 
-  [ a0 setY: a1]; // expected-warning {{multiple methods named 'setY:' found}}
+  [ a0 setY: a1];
 }
 
 void f5(id a0, Abstract *a1) { 
-  [ a0 setZ: a1]; // expected-warning {{multiple methods named 'setZ:' found}}
+  [ a0 setZ: a1];
 }