]> granicus.if.org Git - clang/commitdiff
Fix the atomics sema code to convert operands to the argument types
authorChris Lattner <sabre@nondot.org>
Fri, 8 May 2009 15:36:58 +0000 (15:36 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 8 May 2009 15:36:58 +0000 (15:36 +0000)
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

lib/Sema/SemaChecking.cpp
test/CodeGen/atomic.c
test/Sema/builtins.c

index e8b908ed3f3680809424e83fca2ee0c2e4b2c786..edb5a494665ee74e541e8f82d92da08cf6fd91fc 100644 (file)
@@ -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());
index c224cbdeba6ff51bd1ff06b33e5ac149781f5577..0e7af23f7a1b7dc6b590ca4338b48e8a9443a9aa 100644 (file)
@@ -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;
 }
index c6ef5ea0d155078e19543cda317f4d7642975c97..e57aec51bc557ca44e61bb824c00b7dbaf7f4a7c 100644 (file)
@@ -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}}
 }