r270808 - [ObjC] Remove _Atomic from return type and parameter type of

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Wed May 25 17:37:31 PDT 2016


Author: ahatanak
Date: Wed May 25 19:37:30 2016
New Revision: 270808

URL: http://llvm.org/viewvc/llvm-project?rev=270808&view=rev
Log:
[ObjC] Remove _Atomic from return type and parameter type of
objective-c properties.

This fixes an assert in CodeGen that fires when the getter and setter
functions for an objective-c property of type _Atomic(_Bool) are
synthesized.

rdar://problem/26322972

Differential Revision: http://reviews.llvm.org/D20407

Added:
    cfe/trunk/test/CodeGenObjC/property-atomic-bool.m
    cfe/trunk/test/SemaObjC/property-atomic-bool.m
Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=270808&r1=270807&r2=270808&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed May 25 19:37:30 2016
@@ -1080,6 +1080,9 @@ public:
   /// Strip Objective-C "__kindof" types from the given type.
   QualType stripObjCKindOfType(const ASTContext &ctx) const;
 
+  /// Remove all qualifiers including _Atomic.
+  QualType getAtomicUnqualifiedType() const;
+
 private:
   // These methods are implemented in a separate translation unit;
   // "static"-ize them to avoid creating temporary QualTypes in the

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=270808&r1=270807&r2=270808&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed May 25 19:37:30 2016
@@ -1274,6 +1274,12 @@ QualType QualType::stripObjCKindOfType(c
            });
 }
 
+QualType QualType::getAtomicUnqualifiedType() const {
+  if (auto AT = getTypePtr()->getAs<AtomicType>())
+    return AT->getValueType().getUnqualifiedType();
+  return getUnqualifiedType();
+}
+
 Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
                                const DeclContext *dc) const {
   // Look through method scopes.

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=270808&r1=270807&r2=270808&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Wed May 25 19:37:30 2016
@@ -897,9 +897,8 @@ CodeGenFunction::generateObjCGetterBody(
 
     // Currently, all atomic accesses have to be through integer
     // types, so there's no point in trying to pick a prettier type.
-    llvm::Type *bitcastType =
-      llvm::Type::getIntNTy(getLLVMContext(),
-                            getContext().toBits(strategy.getIvarSize()));
+    uint64_t ivarSize = getContext().toBits(strategy.getIvarSize());
+    llvm::Type *bitcastType = llvm::Type::getIntNTy(getLLVMContext(), ivarSize);
     bitcastType = bitcastType->getPointerTo(); // addrspace 0 okay
 
     // Perform an atomic load.  This does not impose ordering constraints.
@@ -911,7 +910,16 @@ CodeGenFunction::generateObjCGetterBody(
     // Store that value into the return address.  Doing this with a
     // bitcast is likely to produce some pretty ugly IR, but it's not
     // the *most* terrible thing in the world.
-    Builder.CreateStore(load, Builder.CreateBitCast(ReturnValue, bitcastType));
+    llvm::Type *retTy = ConvertType(getterMethod->getReturnType());
+    uint64_t retTySize = CGM.getDataLayout().getTypeSizeInBits(retTy);
+    llvm::Value *ivarVal = load;
+    if (ivarSize > retTySize) {
+      llvm::Type *newTy = llvm::Type::getIntNTy(getLLVMContext(), retTySize);
+      ivarVal = Builder.CreateTrunc(load, newTy);
+      bitcastType = newTy->getPointerTo();
+    }
+    Builder.CreateStore(ivarVal,
+                        Builder.CreateBitCast(ReturnValue, bitcastType));
 
     // Make sure we don't do an autorelease.
     AutoreleaseResult = false;
@@ -1010,7 +1018,6 @@ CodeGenFunction::generateObjCGetterBody(
           AutoreleaseResult = false;
         }
 
-        value = Builder.CreateBitCast(value, ConvertType(propType));
         value = Builder.CreateBitCast(
             value, ConvertType(GetterMethodDecl->getReturnType()));
       }

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=270808&r1=270807&r2=270808&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Wed May 25 19:37:30 2016
@@ -1493,24 +1493,26 @@ bool Sema::DiagnosePropertyAccessorMisma
   if (!GetterMethod)
     return false;
   QualType GetterType = GetterMethod->getReturnType().getNonReferenceType();
-  QualType PropertyIvarType = property->getType().getNonReferenceType();
-  bool compat = Context.hasSameType(PropertyIvarType, GetterType);
+  QualType PropertyRValueType =
+      property->getType().getNonReferenceType().getAtomicUnqualifiedType();
+  bool compat = Context.hasSameType(PropertyRValueType, GetterType);
   if (!compat) {
     const ObjCObjectPointerType *propertyObjCPtr = nullptr;
     const ObjCObjectPointerType *getterObjCPtr = nullptr;
-    if ((propertyObjCPtr = PropertyIvarType->getAs<ObjCObjectPointerType>()) && 
+    if ((propertyObjCPtr =
+             PropertyRValueType->getAs<ObjCObjectPointerType>()) &&
         (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>()))
       compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr);
-    else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType) 
+    else if (CheckAssignmentConstraints(Loc, GetterType, PropertyRValueType)
               != Compatible) {
           Diag(Loc, diag::error_property_accessor_type)
-            << property->getDeclName() << PropertyIvarType
+            << property->getDeclName() << PropertyRValueType
             << GetterMethod->getSelector() << GetterType;
           Diag(GetterMethod->getLocation(), diag::note_declared_at);
           return true;
     } else {
       compat = true;
-      QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
+      QualType lhsType = Context.getCanonicalType(PropertyRValueType);
       QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType();
       if (lhsType != rhsType && lhsType->isArithmeticType())
         compat = false;
@@ -2204,8 +2206,11 @@ void Sema::ProcessPropertyDecl(ObjCPrope
     // for this class.
     SourceLocation Loc = property->getLocation();
 
+    // The getter returns the declared property type with all qualifiers
+    // removed.
+    QualType resultTy = property->getType().getAtomicUnqualifiedType();
+
     // If the property is null_resettable, the getter returns nonnull.
-    QualType resultTy = property->getType();
     if (property->getPropertyAttributes() &
         ObjCPropertyDecl::OBJC_PR_null_resettable) {
       QualType modifiedTy = resultTy;
@@ -2274,9 +2279,12 @@ void Sema::ProcessPropertyDecl(ObjCPrope
                                 ObjCMethodDecl::Optional :
                                 ObjCMethodDecl::Required);
 
+      // Remove all qualifiers from the setter's parameter type.
+      QualType paramTy =
+          property->getType().getUnqualifiedType().getAtomicUnqualifiedType();
+
       // If the property is null_resettable, the setter accepts a
       // nullable value.
-      QualType paramTy = property->getType().getUnqualifiedType();
       if (property->getPropertyAttributes() &
           ObjCPropertyDecl::OBJC_PR_null_resettable) {
         QualType modifiedTy = paramTy;

Added: cfe/trunk/test/CodeGenObjC/property-atomic-bool.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/property-atomic-bool.m?rev=270808&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/property-atomic-bool.m (added)
+++ cfe/trunk/test/CodeGenObjC/property-atomic-bool.m Wed May 25 19:37:30 2016
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10 -emit-llvm -x objective-c %s -o - | FileCheck %s
+
+// CHECK: define internal zeroext i1 @"\01-[A0 p]"(
+// CHECK:   %[[ATOMIC_LOAD:.*]] = load atomic i8, i8* %{{.*}} seq_cst
+// CHECK:   %[[TOBOOL:.*]] = trunc i8 %[[ATOMIC_LOAD]] to i1
+// CHECK:   ret i1 %[[TOBOOL]]
+
+// CHECK: define internal void @"\01-[A0 setP:]"({{.*}} i1 zeroext {{.*}})
+// CHECK:   store atomic i8 %{{.*}}, i8* %{{.*}} seq_cst
+// CHECK:   ret void
+
+// CHECK: define internal zeroext i1 @"\01-[A1 p]"(
+// CHECK:   %[[ATOMIC_LOAD:.*]] = load atomic i8, i8* %{{.*}} unordered
+// CHECK:   %[[TOBOOL:.*]] = trunc i8 %load to i1
+// CHECK:   ret i1 %[[TOBOOL]]
+
+// CHECK: define internal void @"\01-[A1 setP:]"({{.*}} i1 zeroext %p)
+// CHECK:   store atomic i8 %{{.*}}, i8* %{{.*}} unordered
+// CHECK:   ret void
+
+ at interface A0
+ at property(nonatomic) _Atomic(_Bool) p;
+ at end
+ at implementation A0
+ at end
+
+ at interface A1 {
+  _Atomic(_Bool) p;
+}
+ at property _Atomic(_Bool) p;
+ at end
+ at implementation A1
+ at synthesize p;
+ at end

Added: cfe/trunk/test/SemaObjC/property-atomic-bool.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-atomic-bool.m?rev=270808&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/property-atomic-bool.m (added)
+++ cfe/trunk/test/SemaObjC/property-atomic-bool.m Wed May 25 19:37:30 2016
@@ -0,0 +1,61 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -ast-dump "%s" 2>&1 | FileCheck %s
+
+// CHECK: TypedefDecl {{.*}} referenced AtomicBool '_Atomic(_Bool)'
+// CHECK:  AtomicType {{.*}} '_Atomic(_Bool)'
+// CHECK:   BuiltinType {{.*}} '_Bool'
+// CHECK: ObjCInterfaceDecl {{.*}} A0
+// CHECK:  ObjCPropertyDecl {{.*}} p '_Atomic(_Bool)' {{.*}} nonatomic
+// CHECK:  ObjCMethodDecl {{.*}} implicit - p '_Bool'
+// CHECK:  ObjCMethodDecl {{.*}} implicit - setP: 'void'
+// CHECK:   ParmVarDecl {{.*}} p '_Bool'
+// CHECK: ObjCInterfaceDecl {{.*}} A1
+// CHECK:  ObjCPropertyDecl {{.*}} p 'AtomicBool':'_Atomic(_Bool)' {{.*}} nonatomic
+// CHECK:  ObjCMethodDecl {{.*}} implicit - p '_Bool'
+// CHECK:  ObjCMethodDecl {{.*}} implicit - setP: 'void'
+// CHECK:   ParmVarDecl {{.*}} p '_Bool'
+// CHECK: ObjCInterfaceDecl {{.*}} A2
+// CHECK:  ObjCIvarDecl {{.*}} p '_Atomic(_Bool)' protected
+// CHECK:  ObjCPropertyDecl {{.*}} p '_Atomic(_Bool)'
+// CHECK:  ObjCMethodDecl {{.*}} implicit - p '_Bool'
+// CHECK:  ObjCMethodDecl {{.*}} implicit - setP: 'void'
+// CHECK:   ParmVarDecl {{.*}} p '_Bool'
+// CHECK: ObjCInterfaceDecl {{.*}} A3
+// CHECK:  ObjCIvarDecl {{.*}} p 'AtomicBool':'_Atomic(_Bool)' protected
+// CHECK:  ObjCPropertyDecl {{.*}} p 'AtomicBool':'_Atomic(_Bool)'
+// CHECK:  ObjCMethodDecl {{.*}} implicit - p '_Bool'
+// CHECK:  ObjCMethodDecl {{.*}} implicit - setP: 'void'
+// CHECK:   ParmVarDecl {{.*}} p '_Bool'
+
+typedef _Atomic(_Bool) AtomicBool;
+
+ at interface A0
+ at property(nonatomic) _Atomic(_Bool) p;
+ at end
+ at implementation A0
+ at end
+
+ at interface A1
+ at property(nonatomic) AtomicBool p;
+ at end
+ at implementation A1
+ at end
+
+ at interface A2 {
+  _Atomic(_Bool) p;
+}
+ at property _Atomic(_Bool) p;
+ at end
+
+ at implementation A2
+ at synthesize p;
+ at end
+
+ at interface A3 {
+  AtomicBool p;
+}
+ at property AtomicBool p;
+ at end
+
+ at implementation A3
+ at synthesize p;
+ at end




More information about the cfe-commits mailing list