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);