aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-05-08 15:36:58 +0000
committerChris Lattner <sabre@nondot.org>2009-05-08 15:36:58 +0000
commite7ac0a94f1dee3fae9292eb8372962b6d70b3e0d (patch)
treee7166159934f4487a36f1ee341ceb232f3904c49
parent008fc73ac971e5d30c8710e37e1f5f8a843052f1 (diff)
Fix the atomics sema code to convert operands to the argument types
of the underlying _N builtin, not the the type of the pointee of the actual type. This ensures that atomics involving pointers end up using the correct integer type when they are resolved, avoiding aborts in codegen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71218 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaChecking.cpp27
-rw-r--r--test/CodeGen/atomic.c5
-rw-r--r--test/Sema/builtins.c2
3 files changed, 24 insertions, 10 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index e8b908ed3f..edb5a49466 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -293,6 +293,25 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
<< 0 << TheCall->getCallee()->getSourceRange();
+
+ // Get the decl for the concrete builtin from this, we can tell what the
+ // concrete integer type we should convert to is.
+ unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
+ const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID);
+ IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName);
+ FunctionDecl *NewBuiltinDecl =
+ cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID,
+ TUScope, false, DRE->getLocStart()));
+ const FunctionProtoType *BuiltinFT =
+ NewBuiltinDecl->getType()->getAsFunctionProtoType();
+ ValType = BuiltinFT->getArgType(0)->getAsPointerType()->getPointeeType();
+
+ // If the first type needs to be converted (e.g. void** -> int*), do it now.
+ if (BuiltinFT->getArgType(0) != FirstArg->getType()) {
+ ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), false);
+ TheCall->setArg(0, FirstArg);
+ }
+
// Next, walk the valid ones promoting to the right type.
for (unsigned i = 0; i != NumFixed; ++i) {
Expr *Arg = TheCall->getArg(i+1);
@@ -321,14 +340,6 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {
TheCall->setArg(i+1, Arg);
}
- // Okay, if we get here, everything is good. Get the decl for the concrete
- // builtin.
- unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
- const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID);
- IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName);
- FunctionDecl *NewBuiltinDecl =
- cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID,
- TUScope, false, DRE->getLocStart()));
// Switch the DeclRefExpr to refer to the new decl.
DRE->setDecl(NewBuiltinDecl);
DRE->setType(NewBuiltinDecl->getType());
diff --git a/test/CodeGen/atomic.c b/test/CodeGen/atomic.c
index c224cbdeba..0e7af23f7a 100644
--- a/test/CodeGen/atomic.c
+++ b/test/CodeGen/atomic.c
@@ -6,7 +6,7 @@
// RUN: grep @llvm.atomic.load.umin.i32 %t1 &&
// RUN: grep @llvm.atomic.load.umax.i32 %t1 &&
// RUN: grep @llvm.atomic.swap.i32 %t1 &&
-// RUN: grep @llvm.atomic.cmp.swap.i32 %t1 | count 3 &&
+// RUN: grep @llvm.atomic.cmp.swap.i32 %t1 | count 4 &&
// RUN: grep @llvm.atomic.load.and.i32 %t1 | count 2 &&
// RUN: grep @llvm.atomic.load.or.i8 %t1 &&
// RUN: grep @llvm.atomic.load.xor.i8 %t1
@@ -40,5 +40,8 @@ int atomic(void)
old = __sync_or_and_fetch(&valc, 4);
old = __sync_xor_and_fetch(&valc, 5);
+
+ __sync_val_compare_and_swap((void **)0, (void *)0, (void *)0);
+
return old;
}
diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c
index c6ef5ea0d1..e57aec51bc 100644
--- a/test/Sema/builtins.c
+++ b/test/Sema/builtins.c
@@ -48,5 +48,5 @@ unsigned char test9(short v) {
old = __sync_fetch_and_add(); // expected-error {{too few arguments to function call}}
old = __sync_fetch_and_add(&old); // expected-error {{too few arguments to function call}}
- old = __sync_fetch_and_add((int**)0, 42i); // expected-error {{operand of type '_Complex int' cannot be cast to a pointer type}} expected-warning {{imaginary constants are an extension}}
+ old = __sync_fetch_and_add((int**)0, 42i); // expected-warning {{imaginary constants are an extension}}
}