diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 8 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 10 | ||||
-rw-r--r-- | include/clang/Sema/Initialization.h | 12 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 51 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 20 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 6 | ||||
-rw-r--r-- | test/CodeGen/vla.c | 16 |
13 files changed, 128 insertions, 29 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index b1369a4757..cd6bd09d32 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -568,6 +568,14 @@ public: 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. diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 92e62a58d4..9b32836a16 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -3281,7 +3281,17 @@ inline bool QualType::isCanonical() const { 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); } diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 2ba6cdfd56..e0f518bef8 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -152,16 +152,20 @@ public: } /// \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; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 4b4c56502b..fdeac1ebf8 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1413,6 +1413,54 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, 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 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) { // 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 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) { 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 055e3f7e67..73e94d1ece 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -209,17 +209,8 @@ public: } 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 c2016e8386..5e301b5218 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -625,6 +625,9 @@ llvm::Value *CodeGenFunction::EmitVLASize(QualType Ty) { 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 7403711155..8dc8ac1e3d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1714,12 +1714,26 @@ private: 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 00f71a2bd4..b171d85ee0 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -125,7 +125,8 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, // 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 51ef01fce8..c22b5e5bb6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3435,7 +3435,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, // 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 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, 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 @@ void Sema::ConvertPropertyAssignment(Expr *LHS, Expr *&RHS, QualType& LHSTy) { 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 80dbe459ce..f30fcf7312 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1194,6 +1194,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, 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 e9295ebb24..a9c7a727f1 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -241,7 +241,8 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, << 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 bd971b793a..696e5b289c 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -6864,6 +6864,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // Convert the arguments. ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, FnDecl->getParamDecl(0)), SourceLocation(), Input); @@ -7045,6 +7046,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ExprResult Arg1 = PerformCopyInitialization( InitializedEntity::InitializeParameter( + Context, FnDecl->getParamDecl(0)), SourceLocation(), Owned(Args[1])); @@ -7061,6 +7063,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ExprResult Arg0 = PerformCopyInitialization( InitializedEntity::InitializeParameter( + Context, FnDecl->getParamDecl(0)), SourceLocation(), Owned(Args[0])); @@ -7070,6 +7073,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ExprResult Arg1 = PerformCopyInitialization( InitializedEntity::InitializeParameter( + Context, FnDecl->getParamDecl(1)), SourceLocation(), Owned(Args[1])); @@ -7229,6 +7233,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Convert the arguments. ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, FnDecl->getParamDecl(0)), SourceLocation(), Owned(Args[1])); @@ -7666,6 +7671,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, Method->getParamDecl(i)), SourceLocation(), Arg); diff --git a/test/CodeGen/vla.c b/test/CodeGen/vla.c index 8011497bf5..06d17b88d3 100644 --- a/test/CodeGen/vla.c +++ b/test/CodeGen/vla.c @@ -52,10 +52,24 @@ void f_8403108(unsigned x) { } // 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]); } |