QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals);
+
+ /// getUnknownSizeVariableArrayType - Return a variable array type with
+ /// all variable indices replaced with unknow [*] size.
+ QualType getUnknownSizeVariableArrayType(QualType Ty);
+
+ /// getVariableArrayDecayedType - Returns a vla type where known sizes
+ /// are replaced with [*]
+ QualType getVariableArrayDecayedType(QualType Ty);
/// getVectorType - Return the unique reference to a vector type of
/// the specified element type and size. VectorType must be a built-in type.
inline bool QualType::isCanonicalAsParam() const {
if (hasLocalQualifiers()) return false;
+
const Type *T = getTypePtr();
+ if ((*this)->isPointerType()) {
+ QualType BaseType = (*this)->getAs<PointerType>()->getPointeeType();
+ if (isa<VariableArrayType>(BaseType)) {
+ ArrayType *AT = dyn_cast<ArrayType>(BaseType);
+ VariableArrayType *VAT = cast<VariableArrayType>(AT);
+ if (VAT->getSizeExpr())
+ T = BaseType.getTypePtr();
+ }
+ }
return T->isCanonicalUnqualified() &&
!isa<FunctionType>(T) && !isa<ArrayType>(T);
}
}
/// \brief Create the initialization entity for a parameter.
- static InitializedEntity InitializeParameter(ParmVarDecl *Parm) {
- return InitializedEntity(Parm);
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ ParmVarDecl *Parm) {
+ InitializedEntity Res(Parm);
+ Res.Type = Context.getVariableArrayDecayedType(Res.Type);
+ return Res;
}
/// \brief Create the initialization entity for a parameter that is
/// only known by its type.
- static InitializedEntity InitializeParameter(QualType Type) {
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ QualType Type) {
InitializedEntity Entity;
Entity.Kind = EK_Parameter;
- Entity.Type = Type;
+ Entity.Type = Context.getVariableArrayDecayedType(Type);
Entity.Parent = 0;
Entity.VariableOrMember = 0;
return Entity;
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,
// 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));
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,
}
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);
}
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) {
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));
}
// 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);
// 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());
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));
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>();
}
}
for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
ExprResult Result
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
FnDecl->getParamDecl(i)),
SourceLocation(),
Owned(Args[i]->Retain()));
<< argExpr->getSourceRange()))
return true;
- InitializedEntity Entity = InitializedEntity::InitializeParameter(Param);
+ InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+ Param);
ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(argExpr->Retain()));
// Convert the arguments.
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
FnDecl->getParamDecl(0)),
SourceLocation(),
Input);
ExprResult Arg1
= PerformCopyInitialization(
InitializedEntity::InitializeParameter(
+ Context,
FnDecl->getParamDecl(0)),
SourceLocation(),
Owned(Args[1]));
ExprResult Arg0
= PerformCopyInitialization(
InitializedEntity::InitializeParameter(
+ Context,
FnDecl->getParamDecl(0)),
SourceLocation(),
Owned(Args[0]));
ExprResult Arg1
= PerformCopyInitialization(
InitializedEntity::InitializeParameter(
+ Context,
FnDecl->getParamDecl(1)),
SourceLocation(),
Owned(Args[1]));
// Convert the arguments.
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
FnDecl->getParamDecl(0)),
SourceLocation(),
Owned(Args[1]));
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ Context,
Method->getParamDecl(i)),
SourceLocation(), Arg);
}
// pr7827
-void function(short width, int data[][width]) {}
+void function(short width, int data[][width]) {} // expected-note {{passing argument to parameter 'data' here}}
void test() {
+ int bork[4][13];
// CHECK: call void @function(i16 signext 1, i32* null)
function(1, 0);
+ // CHECK: call void @function(i16 signext 1, i32* inttoptr
+ function(1, 0xbadbeef); // expected-warning {{incompatible integer to pointer conversion passing}}
+ // CHECK: call void @function(i16 signext 1, i32* {{.*}})
+ function(1, bork);
+}
+
+void function1(short width, int data[][width][width]) {}
+void test1() {
+ int bork[4][13][15];
+ // CHECK: call void @function1(i16 signext 1, i32* {{.*}})
+ function1(1, bork);
+ // CHECK: call void @function(i16 signext 1, i32* {{.*}})
+ function(1, bork[2]);
}