Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -1080,6 +1080,9 @@ /// Strip Objective-C "__kindof" types from the given type. QualType stripObjCKindOfType(const ASTContext &ctx) const; + /// Strip typedefs and atomic from the given type. + QualType getDesugaredAtomicValueType(const ASTContext &ctx) const; + private: // These methods are implemented in a separate translation unit; // "static"-ize them to avoid creating temporary QualTypes in the Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -1274,6 +1274,13 @@ }); } +QualType QualType::getDesugaredAtomicValueType(const ASTContext &Ctx) const { + auto *TP = getDesugaredType(Ctx).getTypePtrOrNull(); + if (auto *AT = dyn_cast_or_null(TP)) + return AT->getValueType(); + return *this; +} + Optional> Type::getObjCSubstitutions( const DeclContext *dc) const { // Look through method scopes. Index: lib/CodeGen/CGObjC.cpp =================================================================== --- lib/CodeGen/CGObjC.cpp +++ lib/CodeGen/CGObjC.cpp @@ -897,9 +897,8 @@ // 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 @@ // 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,9 @@ AutoreleaseResult = false; } - value = Builder.CreateBitCast(value, ConvertType(propType)); + value = Builder.CreateBitCast( + value, + ConvertType(propType.getDesugaredAtomicValueType(getContext()))); value = Builder.CreateBitCast( value, ConvertType(GetterMethodDecl->getReturnType())); } Index: lib/Sema/SemaDeclObjC.cpp =================================================================== --- lib/Sema/SemaDeclObjC.cpp +++ lib/Sema/SemaDeclObjC.cpp @@ -4315,8 +4315,9 @@ } ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create( - Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, CurContext, - MethodType == tok::minus, isVariadic, + Context, MethodLoc, EndLoc, Sel, + resultDeclType.getDesugaredAtomicValueType(Context), + ReturnTInfo, CurContext, MethodType == tok::minus, isVariadic, /*isPropertyAccessor=*/false, /*isImplicitlyDeclared=*/false, /*isDefined=*/false, MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional @@ -4355,9 +4356,9 @@ ? DI->getTypeLoc().getBeginLoc() : ArgInfo[i].NameLoc; - ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc, - ArgInfo[i].NameLoc, ArgInfo[i].Name, - ArgType, DI, SC_None); + ParmVarDecl* Param = CheckParameter( + ObjCMethod, StartLoc, ArgInfo[i].NameLoc, ArgInfo[i].Name, + ArgType.getDesugaredAtomicValueType(Context), DI, SC_None); Param->setObjCMethodScopeInfo(i); Index: lib/Sema/SemaObjCProperty.cpp =================================================================== --- lib/Sema/SemaObjCProperty.cpp +++ lib/Sema/SemaObjCProperty.cpp @@ -1494,6 +1494,7 @@ return false; QualType GetterType = GetterMethod->getReturnType().getNonReferenceType(); QualType PropertyIvarType = property->getType().getNonReferenceType(); + PropertyIvarType = PropertyIvarType.getDesugaredAtomicValueType(Context); bool compat = Context.hasSameType(PropertyIvarType, GetterType); if (!compat) { const ObjCObjectPointerType *propertyObjCPtr = nullptr; @@ -2205,7 +2206,8 @@ SourceLocation Loc = property->getLocation(); // If the property is null_resettable, the getter returns nonnull. - QualType resultTy = property->getType(); + QualType resultTy = + property->getType().getDesugaredAtomicValueType(Context); if (property->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_null_resettable) { QualType modifiedTy = resultTy; @@ -2277,6 +2279,7 @@ // If the property is null_resettable, the setter accepts a // nullable value. QualType paramTy = property->getType().getUnqualifiedType(); + paramTy = paramTy.getDesugaredAtomicValueType(Context); if (property->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_null_resettable) { QualType modifiedTy = paramTy; Index: test/CodeGenObjC/property-atomic-bool.m =================================================================== --- /dev/null +++ test/CodeGenObjC/property-atomic-bool.m @@ -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 + +@interface A0 +@property(nonatomic) _Atomic(_Bool) p; +@end +@implementation A0 +@end + +@interface A1 { + _Atomic(_Bool) p; +} +@property _Atomic(_Bool) p; +@end +@implementation A1 +@synthesize p; +@end Index: test/SemaObjC/property-atomic-bool.m =================================================================== --- /dev/null +++ test/SemaObjC/property-atomic-bool.m @@ -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; + +@interface A0 +@property(nonatomic) _Atomic(_Bool) p; +@end +@implementation A0 +@end + +@interface A1 +@property(nonatomic) AtomicBool p; +@end +@implementation A1 +@end + +@interface A2 { + _Atomic(_Bool) p; +} +@property _Atomic(_Bool) p; +@end + +@implementation A2 +@synthesize p; +@end + +@interface A3 { + AtomicBool p; +} +@property AtomicBool p; +@end + +@implementation A3 +@synthesize p; +@end