Patch attached.

This patch improves VisitImplicitCastExpr in a few ways.  One, it
deals with lvalues correctly, so code like:
struct s {int i[5];} val;
int* t = val.i;
would work (and not crash) if isConstantExpr let it through.
(isConstantExpr needs some improvements... I've hacked my version to
unconditionally return true for testing.)

Secondly, it deals with subsequent casts correctly, so that code like
"int zzzz[] = {zzzz};" doesn't crash in codegen and returns the right
result.

The change to the function type handling doesn't really make a
difference, but it's a bit more consistent with the wording in the
standard.

-Eli
Index: CodeGen/CGExprConstant.cpp
===================================================================
--- CodeGen/CGExprConstant.cpp  (revision 46389)
+++ CodeGen/CGExprConstant.cpp  (working copy)
@@ -130,38 +181,36 @@
     
     return llvm::ConstantArray::get(AType, Elts);    
   }
-  
+
   llvm::Constant *VisitImplicitCastExpr(ImplicitCastExpr *ICExpr) {
-    // If this is due to array->pointer conversion, emit the array expression 
as
-    // an l-value.
-    if (ICExpr->getSubExpr()->getType()->isArrayType()) {
-      // Note that VLAs can't exist for global variables.
-      // The only thing that can have array type like this is a
-      // DeclRefExpr(FileVarDecl)?
-      const DeclRefExpr *DRE = cast<DeclRefExpr>(ICExpr->getSubExpr());
-      const VarDecl *VD = cast<VarDecl>(DRE->getDecl());
-      llvm::Constant *C = CGM.GetAddrOfGlobalVar(VD, false);
-      assert(isa<llvm::PointerType>(C->getType()) &&
-             isa<llvm::ArrayType>(cast<llvm::PointerType>(C->getType())
-                                  ->getElementType()));
+    Expr* SExpr = ICExpr->getSubExpr();
+    QualType SType = SExpr->getType();
+    llvm::Constant *C; // the intermediate expression
+    QualType T;        // the type of the intermediate expression
+    if (SType->isArrayType()) {
+      // Arrays decay to a pointer to the first element
+      C = EmitLValue(SExpr);
       llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
-      
       llvm::Constant *Ops[] = {Idx0, Idx0};
       C = llvm::ConstantExpr::getGetElementPtr(C, Ops, 2);
-      
-      // The resultant pointer type can be implicitly cast to other pointer
-      // types as well, for example void*.
-      const llvm::Type *DestPTy = ConvertType(ICExpr->getType());
-      assert(isa<llvm::PointerType>(DestPTy) &&
-             "Only expect implicit cast to pointer");
-      return llvm::ConstantExpr::getBitCast(C, DestPTy);
+
+      QualType ElemType = SType->getAsArrayType()->getElementType();
+      T = CGM.getContext().getPointerType(ElemType);
+    } else if (SType->isFunctionType()) {
+      // Function types decay to a pointer to the function
+      C = EmitLValue(SExpr);
+      T = CGM.getContext().getPointerType(SType);
+    } else {
+      C = Visit(SExpr);
+      T = SType;
     }
-    
-    llvm::Constant *C = Visit(ICExpr->getSubExpr());
-    
-    return EmitConversion(C, 
ICExpr->getSubExpr()->getType(),ICExpr->getType());
+
+    // Perform the conversion; note that we always have to go through
+    // this step because an implicit cast can both promote and convert
+    // an array/function
+    return EmitConversion(C, T, ICExpr->getType());
   }
-  
+
   llvm::Constant *VisitStringLiteral(StringLiteral *E) {
     const char *StrData = E->getStrData();
     unsigned Len = E->getByteLength();
_______________________________________________
cfe-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

Reply via email to