Patch implements passing arrays to functions expecting
vla. Implements pr7827.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114737 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4b4c565..fdeac1e 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1413,6 +1413,54 @@
   return QualType(New, 0);
 }
 
+/// getIncompleteArrayType - Returns a unique reference to the type for a
+/// incomplete array of the specified element type.
+QualType ASTContext::getUnknownSizeVariableArrayType(QualType Ty) {
+  QualType ElemTy = getBaseElementType(Ty);
+  DeclarationName Name;
+  llvm::SmallVector<QualType, 8> ATypes;
+  QualType ATy = Ty;
+  while (const ArrayType *AT = getAsArrayType(ATy)) {
+    ATypes.push_back(ATy);
+    ATy = AT->getElementType();
+  }
+  for (int i = ATypes.size() - 1; i >= 0; i--) {
+    if (const VariableArrayType *VAT = getAsVariableArrayType(ATypes[i])) {
+      ElemTy = getVariableArrayType(ElemTy, /*ArraySize*/0, ArrayType::Star,
+                                    0, VAT->getBracketsRange());
+    }
+    else if (const ConstantArrayType *CAT = getAsConstantArrayType(ATypes[i])) {
+      llvm::APSInt ConstVal(CAT->getSize());
+      ElemTy = getConstantArrayType(ElemTy, ConstVal, ArrayType::Normal, 0);
+    }
+    else if (getAsIncompleteArrayType(ATypes[i])) {
+      ElemTy = getVariableArrayType(ElemTy, /*ArraySize*/0, ArrayType::Normal,
+                                    0, SourceRange());
+    }
+    else
+      assert(false && "DependentArrayType is seen");
+  }
+  return ElemTy;
+}
+
+/// getVariableArrayDecayedType - Returns a vla type where known sizes
+/// are replaced with [*]
+QualType ASTContext::getVariableArrayDecayedType(QualType Ty) {
+  if (Ty->isPointerType()) {
+    QualType BaseType = Ty->getAs<PointerType>()->getPointeeType();
+    if (isa<VariableArrayType>(BaseType)) {
+      ArrayType *AT = dyn_cast<ArrayType>(BaseType);
+      VariableArrayType *VAT = cast<VariableArrayType>(AT);
+      if (VAT->getSizeExpr()) {
+        Ty = getUnknownSizeVariableArrayType(BaseType);
+        Ty = getPointerType(Ty);
+      }
+    }
+  }
+  return Ty;
+}
+
+
 /// getVariableArrayType - Returns a non-unique reference to the type for a
 /// variable array of the specified element type.
 QualType ASTContext::getVariableArrayType(QualType EltTy,
@@ -2396,8 +2444,8 @@
   // Push qualifiers into arrays, and then discard any remaining
   // qualifiers.
   T = getCanonicalType(T);
+  T = getVariableArrayDecayedType(T);
   const Type *Ty = T.getTypePtr();
-
   QualType Result;
   if (isa<ArrayType>(Ty)) {
     Result = getArrayDecayedType(QualType(Ty,0));
@@ -2737,7 +2785,6 @@
                                               VAT->getBracketsRange()));
 }
 
-
 /// getArrayDecayedType - Return the properly qualified result of decaying the
 /// specified array type to a pointer.  This operation is non-trivial when
 /// handling typedefs etc.  The canonical type of "T" must be an array type,
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 055e3f7..73e94d1 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -209,17 +209,8 @@
   }
   Value *VisitCastExpr(CastExpr *E) {
     // Make sure to evaluate VLA bounds now so that we have them for later.
-    if (E->getType()->isVariablyModifiedType()) {
-      // Implicit cast of a null pointer to a vla type need not result in vla
-      // size computation which is not always possible in any case (see pr7827).
-      bool NeedSize = true;
-      if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
-        NeedSize = 
-          !ICE->getSubExpr()->isNullPointerConstant(CGF.getContext(),
-                                                Expr::NPC_ValueDependentIsNull);
-      if (NeedSize)
-        CGF.EmitVLASize(E->getType());
-    }
+    if (E->getType()->isVariablyModifiedType())
+      CGF.EmitVLASize(E->getType());
 
     return EmitCastExpr(E);
   }
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index c2016e8..5e301b5 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -625,6 +625,9 @@
   EnsureInsertPoint();
 
   if (const VariableArrayType *VAT = getContext().getAsVariableArrayType(Ty)) {
+    // unknown size indication requires no size computation.
+    if (!VAT->getSizeExpr())
+      return 0;
     llvm::Value *&SizeEntry = VLASizeMap[VAT->getSizeExpr()];
 
     if (!SizeEntry) {
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 7403711..8dc8ac1 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1714,12 +1714,26 @@
            E = CallArgTypeInfo->arg_type_end(); I != E; ++I, ++Arg) {
         assert(Arg != ArgEnd && "Running over edge of argument list!");
         QualType ArgType = *I;
-
+#ifndef NDEBUG
+        QualType ActualArgType = Arg->getType();
+        if (ArgType->isPointerType() && ActualArgType->isPointerType()) {
+          QualType ActualBaseType = 
+            ActualArgType->getAs<PointerType>()->getPointeeType();
+          QualType ArgBaseType = 
+            ArgType->getAs<PointerType>()->getPointeeType();
+          if (ArgBaseType->isVariableArrayType()) {
+            if (const VariableArrayType *VAT =
+                getContext().getAsVariableArrayType(ActualBaseType)) {
+              if (!VAT->getSizeExpr())
+                ActualArgType = ArgType;
+            }
+          }
+        }
         assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
                getTypePtr() ==
-               getContext().getCanonicalType(Arg->getType()).getTypePtr() &&
+               getContext().getCanonicalType(ActualArgType).getTypePtr() &&
                "type mismatch in call argument!");
-
+#endif
         Args.push_back(std::make_pair(EmitCallArg(*Arg, ArgType),
                                       ArgType));
       }
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 00f71a2..b171d85 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -125,7 +125,8 @@
   //   the same semantic constraints as the initializer expression in
   //   a declaration of a variable of the parameter type, using the
   //   copy-initialization semantics (8.5).
-  InitializedEntity Entity = InitializedEntity::InitializeParameter(Param);
+  InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+                                                                    Param);
   InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
                                                            EqualLoc);
   InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 51ef01f..c22b5e5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3435,7 +3435,7 @@
 
     // Check the expression as an initializer for the parameter.
     InitializedEntity Entity
-      = InitializedEntity::InitializeParameter(Param);
+      = InitializedEntity::InitializeParameter(Context, Param);
     InitializationKind Kind
       = InitializationKind::CreateCopy(Param->getLocation(),
              /*FIXME:EqualLoc*/UninstExpr->getSourceRange().getBegin());
@@ -3564,10 +3564,9 @@
       if (FDecl && i < FDecl->getNumParams())
         Param = FDecl->getParamDecl(i);
 
-
       InitializedEntity Entity =
-        Param? InitializedEntity::InitializeParameter(Param)
-             : InitializedEntity::InitializeParameter(ProtoArgType);
+        Param? InitializedEntity::InitializeParameter(Context, Param)
+             : InitializedEntity::InitializeParameter(Context, ProtoArgType);
       ExprResult ArgE = PerformCopyInitialization(Entity,
                                                         SourceLocation(),
                                                         Owned(Arg));
@@ -6232,12 +6231,12 @@
                   LHSTy->isRecordType());
   if (copyInit) {
     InitializedEntity Entity = 
-    InitializedEntity::InitializeParameter(LHSTy);
+    InitializedEntity::InitializeParameter(Context, LHSTy);
     Expr *Arg = RHS;
     ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(),
                                                 Owned(Arg));
     if (!ArgE.isInvalid())
-      RHS = ArgE.takeAs<Expr>();
+      RHS = ArgE.takeAs<Expr>(); 
   }
 }
   
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 80dbe45..f30fcf7 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1194,6 +1194,7 @@
     for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
       ExprResult Result
         = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                       Context,
                                                        FnDecl->getParamDecl(i)),
                                     SourceLocation(),
                                     Owned(Args[i]->Retain()));
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index e9295eb..a9c7a72 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -241,7 +241,8 @@
                               << argExpr->getSourceRange()))
       return true;
 
-    InitializedEntity Entity = InitializedEntity::InitializeParameter(Param);
+    InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+                                                                      Param);
     ExprResult ArgE = PerformCopyInitialization(Entity,
                                                       SourceLocation(),
                                                       Owned(argExpr->Retain()));
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index bd971b7..696e5b2 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -6864,6 +6864,7 @@
         // Convert the arguments.
         ExprResult InputInit
           = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                      Context,
                                                       FnDecl->getParamDecl(0)),
                                       SourceLocation(), 
                                       Input);
@@ -7045,6 +7046,7 @@
           ExprResult Arg1
             = PerformCopyInitialization(
                                         InitializedEntity::InitializeParameter(
+                                                        Context,
                                                         FnDecl->getParamDecl(0)),
                                         SourceLocation(),
                                         Owned(Args[1]));
@@ -7061,6 +7063,7 @@
           ExprResult Arg0
             = PerformCopyInitialization(
                                         InitializedEntity::InitializeParameter(
+                                                        Context,
                                                         FnDecl->getParamDecl(0)),
                                         SourceLocation(),
                                         Owned(Args[0]));
@@ -7070,6 +7073,7 @@
           ExprResult Arg1
             = PerformCopyInitialization(
                                         InitializedEntity::InitializeParameter(
+                                                        Context,
                                                         FnDecl->getParamDecl(1)),
                                         SourceLocation(),
                                         Owned(Args[1]));
@@ -7229,6 +7233,7 @@
         // Convert the arguments.
         ExprResult InputInit
           = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                      Context,
                                                       FnDecl->getParamDecl(0)),
                                       SourceLocation(), 
                                       Owned(Args[1]));
@@ -7666,6 +7671,7 @@
 
       ExprResult InputInit
         = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+                                                    Context,
                                                     Method->getParamDecl(i)),
                                     SourceLocation(), Arg);