]> granicus.if.org Git - clang/commitdiff
fix PR3809, codegen for inc/dec of function pointers.
authorChris Lattner <sabre@nondot.org>
Wed, 18 Mar 2009 04:25:13 +0000 (04:25 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 18 Mar 2009 04:25:13 +0000 (04:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67165 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprScalar.cpp
test/CodeGen/exprs.c

index 1a64e3c905a4adc9608ff0514cf3fb76535c2a15..80aa755e189794fa531e0bc0d97c470f61fb112e 100644 (file)
@@ -627,10 +627,18 @@ Value *ScalarExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
   int AmountVal = isInc ? 1 : -1;
   
   Value *NextVal;
-  if (isa<llvm::PointerType>(InVal->getType())) {
+  if (const llvm::PointerType *PT = 
+         dyn_cast<llvm::PointerType>(InVal->getType())) {
     // FIXME: This isn't right for VLAs.
-    NextVal = llvm::ConstantInt::get(llvm::Type::Int32Ty, AmountVal);
-    NextVal = Builder.CreateGEP(InVal, NextVal, "ptrincdec");
+    llvm::Constant *Inc =llvm::ConstantInt::get(llvm::Type::Int32Ty, AmountVal);
+    if (!isa<llvm::FunctionType>(PT->getElementType())) {
+      NextVal = Builder.CreateGEP(InVal, Inc, "ptrincdec");
+    } else {
+      const llvm::Type *i8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+      NextVal = Builder.CreateBitCast(InVal, i8Ty, "tmp");
+      NextVal = Builder.CreateGEP(NextVal, Inc, "ptrincdec");
+      NextVal = Builder.CreateBitCast(NextVal, InVal->getType());
+    }
   } else if (InVal->getType() == llvm::Type::Int1Ty && isInc) {
     // Bool++ is an interesting case, due to promotion rules, we get:
     // Bool++ -> Bool = Bool+1 -> Bool = (int)Bool+1 ->
index db60b5a3301d8875c7d23326fa2a2a958b2c7b47..c22a4ecc71d6fdb63c50dc129ed2248322e21e04 100644 (file)
@@ -67,3 +67,15 @@ int bar() {
   return ((struct X)foo()).Y + 1;
 }
 
+// PR3809: INC/DEC of function pointers.
+void f2(void);
+unsigned f1(void) {
+  void (*fp)(void) = f2;
+  
+  ++fp;
+  fp++;
+  --fp;
+  fp--;
+  return (unsigned) fp;
+}  
+