aaron.ballman updated this revision to Diff 146472.
aaron.ballman added a comment.
Addresses review comments.
https://reviews.llvm.org/D46112
Files:
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaChecking.cpp
lib/Sema/SemaType.cpp
test/CodeGen/c11atomics.c
test/Sema/atomic-type.c
test/Sema/atomic-type.cpp
Index: test/Sema/atomic-type.cpp
===================================================================
--- test/Sema/atomic-type.cpp
+++ test/Sema/atomic-type.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+struct S;
+
+void f(_Atomic S *s);
+
+struct S { int a, b; };
+
+void f(_Atomic S *s) {
+ S s2;
+ (void)__atomic_load(s, &s2, 5); // expected-error {{address argument to atomic operation must be a pointer to a trivially-copyable type ('_Atomic(S) *' invalid)}}
+ (void)__c11_atomic_load(s, 5);
+}
+
Index: test/Sema/atomic-type.c
===================================================================
--- test/Sema/atomic-type.c
+++ test/Sema/atomic-type.c
@@ -16,7 +16,17 @@
extern _Atomic(int (*)(int(*)[10], int(*)[10])) mergetest;
_Atomic(int()) error1; // expected-error {{_Atomic cannot be applied to function type}}
-_Atomic(struct ErrorS) error2; // expected-error {{_Atomic cannot be applied to incomplete type}} expected-note {{forward declaration}}
+_Atomic(struct ErrorS) error2;
_Atomic(int[10]) error3; // expected-error {{_Atomic cannot be applied to array type}}
_Atomic(const int) error4; // expected-error {{_Atomic cannot be applied to qualified type}}
_Atomic(_Atomic(int)) error5; // expected-error {{_Atomic cannot be applied to atomic type}}
+
+void g(_Atomic void *ptr);
+void h(_Atomic struct Incomplete *ptr); // expected-warning {{declaration of 'struct Incomplete' will not be visible outside of this function}}
+
+void test_atomic_void_ptr(_Atomic void *addr) {
+ int i;
+ (void)__atomic_load(addr, &i, 5); // expected-error {{address argument to atomic operation must be a pointer to a trivially-copyable type ('_Atomic(void) *' invalid)}}
+ (void)__c11_atomic_load(addr, 5); // expected-error {{invalid use of incomplete type 'void'}}
+ _Static_assert(__atomic_is_lock_free(1, addr), "");
+}
Index: test/CodeGen/c11atomics.c
===================================================================
--- test/CodeGen/c11atomics.c
+++ test/CodeGen/c11atomics.c
@@ -61,7 +61,7 @@
// we have to generate an atomic add, which returns the old value, and then a
// non-atomic add.
// CHECK: atomicrmw add i32* @i, i32 1 seq_cst
- // CHECK: add i32
+ // CHECK: add i32
++i;
// CHECK: atomicrmw add i64* @l, i64 1 seq_cst
// CHECK: add i64
@@ -475,6 +475,25 @@
return __c11_atomic_compare_exchange_strong(addr, desired, *new, 5, 5);
}
+int test_atomic_void_ptr(_Atomic void *addr) {
+ // CHECK-LABEL: @test_atomic_void_ptr(
+ // CHECK: [[ADDR_ARG:%.*]] = alloca { i8, [1 x i8] }*, align 4
+ // CHECK: [[ATOMIC_RES:%.*]] = alloca i32, align 4
+ // CHECK: store { i8, [1 x i8] }* %addr, { i8, [1 x i8] }** [[ADDR_ARG]], align 4
+ // CHECK: [[ADDR_LOCK_FREE_VP:%.*]] = load { i8, [1 x i8] }*, { i8, [1 x i8] }** [[ADDR_ARG]], align 4
+ // CHECK: [[ADDR_LOCK_FREE:%.*]] = bitcast { i8, [1 x i8] }* [[ADDR_LOCK_FREE_VP]] to i8*
+ // CHECK: call arm_aapcscc i32 @__atomic_is_lock_free(i32 1, i8* [[ADDR_LOCK_FREE]])
+ // CHECK: [[ADDR:%.*]] = load { i8, [1 x i8] }*, { i8, [1 x i8] }** [[ADDR_ARG]], align 4
+ // CHECK: [[CAST1:%.*]] = bitcast { i8, [1 x i8] }* [[ADDR]] to i32*
+ // CHECK: [[CAST2:%.*]] = bitcast i32* [[CAST1]] to i8*
+ // CHECK: [[CALL:%.*]] = call arm_aapcscc i32 @__atomic_load_4(i8* [[CAST2]], i32 5)
+ // CHECK: store i32 [[CALL]], i32* [[ATOMIC_RES]], align 4
+ // CHECK: [[RES:%.*]] = load i32, i32* [[ATOMIC_RES]], align 4
+ // CHECK: ret i32 [[RES]]
+ (void)__atomic_is_lock_free(1, addr);
+ return (int)__c11_atomic_load((_Atomic int *)addr, 5);
+}
+
struct Empty {};
struct Empty test_empty_struct_load(_Atomic(struct Empty)* empty) {
@@ -488,3 +507,25 @@
// CHECK: call arm_aapcscc void @__atomic_store_1(i8* %{{.*}}, i8 zeroext %{{.*}}, i32 5)
__c11_atomic_store(empty, value, 5);
}
+
+typedef struct T T;
+void test_struct_copy(_Atomic(T) *t1, _Atomic(T) *t2);
+struct T { int a, b; };
+void test_struct_copy(_Atomic(T) *t1, _Atomic(T) *t2) {
+ // CHECK-LABEL: @test_struct_copy(
+ // CHECK: [[T1:%.*]] = alloca %struct.T*, align 4
+ // CHECK: [[T2:%.*]] = alloca %struct.T*, align 4
+ // CHECK: [[TEMP:%.*]] = alloca %struct.T, align 8
+ // CHECK: store %struct.T* %t1, %struct.T** [[T1]], align 4
+ // CHECK: store %struct.T* %t2, %struct.T** [[T2]], align 4
+ // CHECK: [[LOAD1:%.*]] = load %struct.T*, %struct.T** [[T1]], align 4
+ // CHECK: [[LOAD2:%.*]] = load %struct.T*, %struct.T** [[T2]], align 4
+ // CHECK: [[CAST1:%.*]] = bitcast %struct.T* [[LOAD2]] to i8*
+ // CHECK: [[CAST2:%.*]] = bitcast %struct.T* [[TEMP]] to i8*
+ // CHECK: call arm_aapcscc void @__atomic_load(i32 8, i8* [[CAST1]], i8* [[CAST2]], i32 5)
+ // CHECK: [[CAST3:%.*]] = bitcast %struct.T* [[LOAD1]] to i8*
+ // CHECK: [[CAST4:%.*]] = bitcast %struct.T* [[TEMP]] to i8*
+ // CHECK: call arm_aapcscc void @__atomic_store(i32 8, i8* [[CAST3]], i8* [[CAST4]], i32 5)
+ // CHECK: ret void
+ *t1 = *t2;
+}
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -8019,25 +8019,17 @@
QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
if (!T->isDependentType()) {
- // FIXME: It isn't entirely clear whether incomplete atomic types
- // are allowed or not; for simplicity, ban them for the moment.
- if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0))
- return QualType();
-
int DisallowedKind = -1;
if (T->isArrayType())
- DisallowedKind = 1;
+ DisallowedKind = 0;
else if (T->isFunctionType())
- DisallowedKind = 2;
+ DisallowedKind = 1;
else if (T->isReferenceType())
- DisallowedKind = 3;
+ DisallowedKind = 2;
else if (T->isAtomicType())
- DisallowedKind = 4;
+ DisallowedKind = 3;
else if (T.hasQualifiers())
- DisallowedKind = 5;
- else if (!T.isTriviallyCopyableType(Context))
- // Some other non-trivially-copyable type (probably a C++ class)
- DisallowedKind = 6;
+ DisallowedKind = 4;
if (DisallowedKind != -1) {
Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -3144,7 +3144,7 @@
return ExprError();
}
- // For a __c11 builtin, this should be a pointer to an _Atomic type.
+ // For a __c11 builtin, this should be a pointer to a complete _Atomic type.
QualType AtomTy = pointerType->getPointeeType(); // 'A'
QualType ValType = AtomTy; // 'C'
if (IsC11) {
@@ -3161,6 +3161,10 @@
return ExprError();
}
ValType = AtomTy->getAs<AtomicType>()->getValueType();
+
+ if (RequireCompleteType(DRE->getLocStart(), ValType,
+ diag::err_invalid_incomplete_type_use, ValType))
+ return ExprError();
} else if (Form != Load && Form != LoadCopy) {
if (ValType.isConstQualified()) {
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_pointer)
@@ -3195,12 +3199,11 @@
return ExprError();
}
- if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context) &&
- !AtomTy->isScalarType()) {
- // For GNU atomics, require a trivially-copyable type. This is not part of
- // the GNU atomics specification, but we enforce it for sanity.
+ if (!ValType.isTriviallyCopyableType(Context) && !ValType->isScalarType()) {
+ // Always require a trivially-copyable type. This is not part of the GNU
+ // atomics specification, but we enforce it for sanity.
Diag(DRE->getLocStart(), diag::err_atomic_op_needs_trivial_copy)
- << Ptr->getType() << Ptr->getSourceRange();
+ << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -5513,8 +5513,7 @@
"incomplete result type %0 in function definition">;
def err_atomic_specifier_bad_type : Error<
"_Atomic cannot be applied to "
- "%select{incomplete |array |function |reference |atomic |qualified |}0type "
- "%1 %select{||||||which is not trivially copyable}0">;
+ "%select{array|function|reference|atomic|qualified}0 type %1">;
// Expressions.
def ext_sizeof_alignof_function_type : Extension<
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits