[cfe-commits] r104168 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/Sema/SemaDecl.cpp test/SemaObjCXX/objc2-merge-gc-attribue-decl.mm

Fariborz Jahanian fjahanian at apple.com
Wed May 19 14:37:31 PDT 2010


Author: fjahanian
Date: Wed May 19 16:37:30 2010
New Revision: 104168

URL: http://llvm.org/viewvc/llvm-project?rev=104168&view=rev
Log:
Adds support for ObjC++'s GC attribute on declaration of
object variables and functions returning such objects.


Added:
    cfe/trunk/test/SemaObjCXX/objc2-merge-gc-attribue-decl.mm
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=104168&r1=104167&r2=104168&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed May 19 16:37:30 2010
@@ -1193,6 +1193,8 @@
   // Functions for calculating composite types
   QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false);
   QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false);
+  
+  QualType mergeObjCGCQualifiers(QualType, QualType);
 
   /// UsualArithmeticConversionsType - handles the various conversions
   /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=104168&r1=104167&r2=104168&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed May 19 16:37:30 2010
@@ -4661,6 +4661,87 @@
   return QualType();
 }
 
+/// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and
+/// 'RHS' attributes and returns the merged version; including for function
+/// return types.
+QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
+  QualType LHSCan = getCanonicalType(LHS),
+  RHSCan = getCanonicalType(RHS);
+  // If two types are identical, they are compatible.
+  if (LHSCan == RHSCan)
+    return LHS;
+  if (RHSCan->isFunctionType()) {
+    if (!LHSCan->isFunctionType())
+      return QualType();
+    QualType OldReturnType = 
+      cast<FunctionType>(RHSCan.getTypePtr())->getResultType();
+    QualType NewReturnType =
+      cast<FunctionType>(LHSCan.getTypePtr())->getResultType();
+    QualType ResReturnType = 
+      mergeObjCGCQualifiers(NewReturnType, OldReturnType);
+    if (ResReturnType.isNull())
+      return QualType();
+    if (ResReturnType == NewReturnType || ResReturnType == OldReturnType) {
+      // id foo(); ... __strong id foo(); or: __strong id foo(); ... id foo();
+      // In either case, use OldReturnType to build the new function type.
+      const FunctionType *F = LHS->getAs<FunctionType>();
+      if (const FunctionProtoType *FPT = cast<FunctionProtoType>(F)) {
+        FunctionType::ExtInfo Info = getFunctionExtInfo(LHS);
+        QualType ResultType
+          = getFunctionType(OldReturnType, FPT->arg_type_begin(),
+                                  FPT->getNumArgs(), FPT->isVariadic(),
+                                  FPT->getTypeQuals(),
+                                  FPT->hasExceptionSpec(),
+                                  FPT->hasAnyExceptionSpec(),
+                                  FPT->getNumExceptions(),
+                                  FPT->exception_begin(),
+                                  Info);
+        return ResultType;
+      }
+    }
+    return QualType();
+  }
+  
+  // If the qualifiers are different, the types can still be merged.
+  Qualifiers LQuals = LHSCan.getLocalQualifiers();
+  Qualifiers RQuals = RHSCan.getLocalQualifiers();
+  if (LQuals != RQuals) {
+    // If any of these qualifiers are different, we have a type mismatch.
+    if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
+        LQuals.getAddressSpace() != RQuals.getAddressSpace())
+      return QualType();
+    
+    // Exactly one GC qualifier difference is allowed: __strong is
+    // okay if the other type has no GC qualifier but is an Objective
+    // C object pointer (i.e. implicitly strong by default).  We fix
+    // this by pretending that the unqualified type was actually
+    // qualified __strong.
+    Qualifiers::GC GC_L = LQuals.getObjCGCAttr();
+    Qualifiers::GC GC_R = RQuals.getObjCGCAttr();
+    assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements");
+    
+    if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak)
+      return QualType();
+    
+    if (GC_L == Qualifiers::Strong)
+      return LHS;
+    if (GC_R == Qualifiers::Strong)
+      return RHS;
+    return QualType();
+  }
+  
+  if (LHSCan->isObjCObjectPointerType() && RHSCan->isObjCObjectPointerType()) {
+    QualType LHSBaseQT = LHS->getAs<ObjCObjectPointerType>()->getPointeeType();
+    QualType RHSBaseQT = RHS->getAs<ObjCObjectPointerType>()->getPointeeType();
+    QualType ResQT = mergeObjCGCQualifiers(LHSBaseQT, RHSBaseQT);
+    if (ResQT == LHSBaseQT)
+      return LHS;
+    if (ResQT == RHSBaseQT)
+      return RHS;
+  }
+  return QualType();
+}
+
 //===----------------------------------------------------------------------===//
 //                         Integer Predicates
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=104168&r1=104167&r2=104168&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed May 19 16:37:30 2010
@@ -1077,10 +1077,18 @@
       = cast<FunctionType>(OldQType.getTypePtr())->getResultType();
     QualType NewReturnType
       = cast<FunctionType>(NewQType.getTypePtr())->getResultType();
+    QualType ResQT;
     if (OldReturnType != NewReturnType) {
-      Diag(New->getLocation(), diag::err_ovl_diff_return_type);
-      Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
-      return true;
+      if (NewReturnType->isObjCObjectPointerType()
+          && OldReturnType->isObjCObjectPointerType())
+        ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType);
+      if (ResQT.isNull()) {
+        Diag(New->getLocation(), diag::err_ovl_diff_return_type);
+        Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+        return true;
+      }
+      else
+        NewQType = ResQT;
     }
 
     const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
@@ -1364,6 +1372,9 @@
         = Context.getCanonicalType(New->getType())->getAs<ArrayType>();
       if (OldArray->getElementType() == NewArray->getElementType())
         MergedT = Old->getType();
+    } else if (New->getType()->isObjCObjectPointerType()
+               && Old->getType()->isObjCObjectPointerType()) {
+        MergedT = Context.mergeObjCGCQualifiers(New->getType(), Old->getType());
     }
   } else {
     MergedT = Context.mergeTypes(New->getType(), Old->getType());

Added: cfe/trunk/test/SemaObjCXX/objc2-merge-gc-attribue-decl.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/objc2-merge-gc-attribue-decl.mm?rev=104168&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjCXX/objc2-merge-gc-attribue-decl.mm (added)
+++ cfe/trunk/test/SemaObjCXX/objc2-merge-gc-attribue-decl.mm Wed May 19 16:37:30 2010
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-gc -fsyntax-only -verify %s
+ at interface INTF @end
+
+extern INTF* p2;
+extern __strong INTF* p2;
+
+extern __strong id p1;
+extern id p1;
+
+extern id CFRunLoopGetMain();
+extern __strong id CFRunLoopGetMain();
+
+extern __strong id CFRunLoopGetMain2();
+extern id CFRunLoopGetMain2();
+
+extern INTF* CFRunLoopGetMain3();
+extern __strong INTF* CFRunLoopGetMain3();
+
+extern __strong INTF* CFRunLoopGetMain4();
+extern INTF* CFRunLoopGetMain4();
+
+typedef id ID;
+extern ID CFRunLoopGetMain5();
+extern __strong id CFRunLoopGetMain5();
+
+extern __strong id CFRunLoopGetMain6();
+extern ID CFRunLoopGetMain6();
+
+extern ID CFRunLoopGetMain7();
+extern __strong ID CFRunLoopGetMain7();
+
+extern __strong ID CFRunLoopGetMain8();
+extern ID CFRunLoopGetMain8();
+
+extern __weak id WLoopGetMain(); // expected-note {{previous declaration is here}}
+extern id WLoopGetMain();	// expected-error {{functions that differ only in their return type cannot be overloaded}}
+
+extern id p3;	// expected-note {{previous definition is here}}
+extern __weak id p3;	// expected-error {{redefinition of 'p3' with a different type}}
+
+extern void *p4; // expected-note {{previous definition is here}}
+extern void * __strong p4; // expected-error {{redefinition of 'p4' with a different type}}
+
+extern id p5;
+extern __strong id p5;
+
+extern char* __strong p6; // expected-note {{previous definition is here}}
+extern char* p6; // expected-error {{redefinition of 'p6' with a different type}}
+
+extern __strong char* p7; // expected-note {{previous definition is here}}
+extern char* p7; // expected-error {{redefinition of 'p7' with a different type}}





More information about the cfe-commits mailing list