Properly handle instantiation-dependent array bounds.

We previously failed to treat an array with an instantiation-dependent
but not value-dependent bound as being an instantiation-dependent type.
We now track the array bound expression as part of a constant array type
if it's an instantiation-dependent expression.

llvm-svn: 373685
This commit is contained in:
Richard Smith 2019-10-04 01:25:59 +00:00
parent 053391fa86
commit 772e266fbf
31 changed files with 237 additions and 156 deletions

View File

@ -185,7 +185,8 @@ private:
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
mutable llvm::FoldingSet<MemberPointerType> MemberPointerTypes;
mutable llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
mutable llvm::ContextualFoldingSet<ConstantArrayType, ASTContext &>
ConstantArrayTypes;
mutable llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
mutable std::vector<VariableArrayType*> VariableArrayTypes;
mutable llvm::FoldingSet<DependentSizedArrayType> DependentSizedArrayTypes;
@ -1330,6 +1331,7 @@ public:
/// Return the unique reference to the type for a constant array of
/// the specified element type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
const Expr *SizeExpr,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals) const;

View File

@ -959,8 +959,11 @@ DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
DEF_TRAVERSE_TYPE(ConstantArrayType,
{ TRY_TO(TraverseType(T->getElementType())); })
DEF_TRAVERSE_TYPE(ConstantArrayType, {
TRY_TO(TraverseType(T->getElementType()));
if (T->getSizeExpr())
TRY_TO(TraverseStmt(const_cast<Expr*>(T->getSizeExpr())));
})
DEF_TRAVERSE_TYPE(IncompleteArrayType,
{ TRY_TO(TraverseType(T->getElementType())); })

View File

@ -1513,6 +1513,15 @@ protected:
unsigned SizeModifier : 3;
};
class ConstantArrayTypeBitfields {
friend class ConstantArrayType;
unsigned : NumTypeBits + 3 + 3;
/// Whether we have a stored size expression.
unsigned HasStoredSizeExpr : 1;
};
class BuiltinTypeBitfields {
friend class BuiltinType;
@ -1734,6 +1743,7 @@ protected:
union {
TypeBitfields TypeBits;
ArrayTypeBitfields ArrayTypeBits;
ConstantArrayTypeBitfields ConstantArrayTypeBits;
AttributedTypeBitfields AttributedTypeBits;
AutoTypeBitfields AutoTypeBits;
BuiltinTypeBitfields BuiltinTypeBits;
@ -2864,22 +2874,8 @@ private:
protected:
friend class ASTContext; // ASTContext creates these.
// C++ [temp.dep.type]p1:
// A type is dependent if it is...
// - an array type constructed from any dependent type or whose
// size is specified by a constant expression that is
// value-dependent,
ArrayType(TypeClass tc, QualType et, QualType can,
ArraySizeModifier sm, unsigned tq,
bool ContainsUnexpandedParameterPack)
: Type(tc, can, et->isDependentType() || tc == DependentSizedArray,
et->isInstantiationDependentType() || tc == DependentSizedArray,
(tc == VariableArray || et->isVariablyModifiedType()),
ContainsUnexpandedParameterPack),
ElementType(et) {
ArrayTypeBits.IndexTypeQuals = tq;
ArrayTypeBits.SizeModifier = sm;
}
ArrayType(TypeClass tc, QualType et, QualType can, ArraySizeModifier sm,
unsigned tq, const Expr *sz = nullptr);
public:
QualType getElementType() const { return ElementType; }
@ -2907,25 +2903,35 @@ public:
/// Represents the canonical version of C arrays with a specified constant size.
/// For example, the canonical type for 'int A[4 + 4*100]' is a
/// ConstantArrayType where the element type is 'int' and the size is 404.
class ConstantArrayType : public ArrayType {
class ConstantArrayType final
: public ArrayType,
private llvm::TrailingObjects<ConstantArrayType, const Expr *> {
friend class ASTContext; // ASTContext creates these.
friend TrailingObjects;
llvm::APInt Size; // Allows us to unique the type.
ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
ArraySizeModifier sm, unsigned tq)
: ArrayType(ConstantArray, et, can, sm, tq,
et->containsUnexpandedParameterPack()),
Size(size) {}
const Expr *sz, ArraySizeModifier sm, unsigned tq)
: ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) {
ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr;
if (ConstantArrayTypeBits.HasStoredSizeExpr) {
assert(!can.isNull() && "canonical constant array should not have size");
*getTrailingObjects<const Expr*>() = sz;
}
}
protected:
friend class ASTContext; // ASTContext creates these.
ConstantArrayType(TypeClass tc, QualType et, QualType can,
const llvm::APInt &size, ArraySizeModifier sm, unsigned tq)
: ArrayType(tc, et, can, sm, tq, et->containsUnexpandedParameterPack()),
Size(size) {}
unsigned numTrailingObjects(OverloadToken<const Expr*>) const {
return ConstantArrayTypeBits.HasStoredSizeExpr;
}
public:
const llvm::APInt &getSize() const { return Size; }
const Expr *getSizeExpr() const {
return ConstantArrayTypeBits.HasStoredSizeExpr
? *getTrailingObjects<const Expr *>()
: nullptr;
}
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@ -2939,19 +2945,15 @@ public:
/// can require, which limits the maximum size of the array.
static unsigned getMaxSizeBits(const ASTContext &Context);
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getSize(),
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(),
getSizeModifier(), getIndexTypeCVRQualifiers());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ET,
const llvm::APInt &ArraySize, ArraySizeModifier SizeMod,
unsigned TypeQuals) {
ID.AddPointer(ET.getAsOpaquePtr());
ID.AddInteger(ArraySize.getZExtValue());
ID.AddInteger(SizeMod);
ID.AddInteger(TypeQuals);
}
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx,
QualType ET, const llvm::APInt &ArraySize,
const Expr *SizeExpr, ArraySizeModifier SizeMod,
unsigned TypeQuals);
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray;
@ -2966,8 +2968,7 @@ class IncompleteArrayType : public ArrayType {
IncompleteArrayType(QualType et, QualType can,
ArraySizeModifier sm, unsigned tq)
: ArrayType(IncompleteArray, et, can, sm, tq,
et->containsUnexpandedParameterPack()) {}
: ArrayType(IncompleteArray, et, can, sm, tq) {}
public:
friend class StmtIteratorBase;
@ -3019,8 +3020,7 @@ class VariableArrayType : public ArrayType {
VariableArrayType(QualType et, QualType can, Expr *e,
ArraySizeModifier sm, unsigned tq,
SourceRange brackets)
: ArrayType(VariableArray, et, can, sm, tq,
et->containsUnexpandedParameterPack()),
: ArrayType(VariableArray, et, can, sm, tq, e),
SizeExpr((Stmt*) e), Brackets(brackets) {}
public:

View File

@ -829,7 +829,8 @@ static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI,
ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins)
: FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()),
: ConstantArrayTypes(this_()), FunctionProtoTypes(this_()),
TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()),
SubstTemplateTemplateParmPacks(this_()), SourceMgr(SM), LangOpts(LOpts),
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
@ -3165,31 +3166,38 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const {
/// array of the specified element type.
QualType ASTContext::getConstantArrayType(QualType EltTy,
const llvm::APInt &ArySizeIn,
const Expr *SizeExpr,
ArrayType::ArraySizeModifier ASM,
unsigned IndexTypeQuals) const {
assert((EltTy->isDependentType() ||
EltTy->isIncompleteType() || EltTy->isConstantSizeType()) &&
"Constant array of VLAs is illegal!");
// We only need the size as part of the type if it's instantiation-dependent.
if (SizeExpr && !SizeExpr->isInstantiationDependent())
SizeExpr = nullptr;
// Convert the array size into a canonical width matching the pointer size for
// the target.
llvm::APInt ArySize(ArySizeIn);
ArySize = ArySize.zextOrTrunc(Target->getMaxPointerWidth());
llvm::FoldingSetNodeID ID;
ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals);
ConstantArrayType::Profile(ID, *this, EltTy, ArySize, SizeExpr, ASM,
IndexTypeQuals);
void *InsertPos = nullptr;
if (ConstantArrayType *ATP =
ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(ATP, 0);
// If the element type isn't canonical or has qualifiers, this won't
// be a canonical type either, so fill in the canonical type field.
// If the element type isn't canonical or has qualifiers, or the array bound
// is instantiation-dependent, this won't be a canonical type either, so fill
// in the canonical type field.
QualType Canon;
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers() || SizeExpr) {
SplitQualType canonSplit = getCanonicalType(EltTy).split();
Canon = getConstantArrayType(QualType(canonSplit.Ty, 0), ArySize,
Canon = getConstantArrayType(QualType(canonSplit.Ty, 0), ArySize, nullptr,
ASM, IndexTypeQuals);
Canon = getQualifiedType(Canon, canonSplit.Quals);
@ -3199,8 +3207,11 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}
auto *New = new (*this,TypeAlignment)
ConstantArrayType(EltTy, Canon, ArySize, ASM, IndexTypeQuals);
void *Mem = Allocate(
ConstantArrayType::totalSizeToAlloc<const Expr *>(SizeExpr ? 1 : 0),
TypeAlignment);
auto *New = new (Mem)
ConstantArrayType(EltTy, Canon, ArySize, SizeExpr, ASM, IndexTypeQuals);
ConstantArrayTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return QualType(New, 0);
@ -3297,6 +3308,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
result = getConstantArrayType(
getVariableArrayDecayedType(cat->getElementType()),
cat->getSize(),
cat->getSizeExpr(),
cat->getSizeModifier(),
cat->getIndexTypeCVRQualifiers());
break;
@ -5192,7 +5204,7 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
return getConstantArrayType(unqualElementType, CAT->getSize(),
CAT->getSizeModifier(), 0);
CAT->getSizeExpr(), CAT->getSizeModifier(), 0);
}
if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT)) {
@ -5565,6 +5577,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
if (const auto *CAT = dyn_cast<ConstantArrayType>(ATy))
return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
CAT->getSizeExpr(),
CAT->getSizeModifier(),
CAT->getIndexTypeCVRQualifiers()));
if (const auto *IAT = dyn_cast<IncompleteArrayType>(ATy))
@ -7471,7 +7484,7 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) {
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
QualType VaListTagArrayType
= Context->getConstantArrayType(VaListTagTypedefType,
Size, ArrayType::Normal, 0);
Size, nullptr, ArrayType::Normal, 0);
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
}
@ -7524,16 +7537,16 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) {
// typedef struct __va_list_tag __builtin_va_list[1];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
QualType VaListTagArrayType =
Context->getConstantArrayType(VaListTagType, Size, ArrayType::Normal, 0);
QualType VaListTagArrayType = Context->getConstantArrayType(
VaListTagType, Size, nullptr, ArrayType::Normal, 0);
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
}
static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) {
// typedef int __builtin_va_list[4];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 4);
QualType IntArrayType =
Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0);
QualType IntArrayType = Context->getConstantArrayType(
Context->IntTy, Size, nullptr, ArrayType::Normal, 0);
return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list");
}
@ -7627,8 +7640,8 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) {
// typedef __va_list_tag __builtin_va_list[1];
llvm::APInt Size(Context->getTypeSize(Context->getSizeType()), 1);
QualType VaListTagArrayType =
Context->getConstantArrayType(VaListTagType, Size, ArrayType::Normal, 0);
QualType VaListTagArrayType = Context->getConstantArrayType(
VaListTagType, Size, nullptr, ArrayType::Normal, 0);
return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list");
}
@ -9072,10 +9085,14 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return LHS;
if (RCAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
return RHS;
if (LCAT) return getConstantArrayType(ResultType, LCAT->getSize(),
ArrayType::ArraySizeModifier(), 0);
if (RCAT) return getConstantArrayType(ResultType, RCAT->getSize(),
ArrayType::ArraySizeModifier(), 0);
if (LCAT)
return getConstantArrayType(ResultType, LCAT->getSize(),
LCAT->getSizeExpr(),
ArrayType::ArraySizeModifier(), 0);
if (RCAT)
return getConstantArrayType(ResultType, RCAT->getSize(),
RCAT->getSizeExpr(),
ArrayType::ArraySizeModifier(), 0);
if (LVAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
return LHS;
if (RVAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType))
@ -10317,7 +10334,7 @@ QualType ASTContext::getStringLiteralArrayType(QualType EltTy,
// Get an array type for the string, according to C99 6.4.5. This includes
// the null terminator character.
return getConstantArrayType(EltTy, llvm::APInt(32, Length + 1),
return getConstantArrayType(EltTy, llvm::APInt(32, Length + 1), nullptr,
ArrayType::Normal, /*IndexTypeQuals*/ 0);
}

View File

@ -1098,14 +1098,16 @@ ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) {
ExpectedType
ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) {
ExpectedType ToElementTypeOrErr = import(T->getElementType());
if (!ToElementTypeOrErr)
return ToElementTypeOrErr.takeError();
QualType ToElementType;
const Expr *ToSizeExpr;
if (auto Imp = importSeq(T->getElementType(), T->getSizeExpr()))
std::tie(ToElementType, ToSizeExpr) = *Imp;
else
return Imp.takeError();
return Importer.getToContext().getConstantArrayType(*ToElementTypeOrErr,
T->getSize(),
T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
return Importer.getToContext().getConstantArrayType(
ToElementType, T->getSize(), ToSizeExpr, T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
}
ExpectedType

View File

@ -6004,8 +6004,8 @@ static bool HandleOperatorNewCall(EvalInfo &Info, const CallExpr *E,
return false;
}
QualType AllocType =
Info.Ctx.getConstantArrayType(ElemType, Size, ArrayType::Normal, 0);
QualType AllocType = Info.Ctx.getConstantArrayType(ElemType, Size, nullptr,
ArrayType::Normal, 0);
APValue *Val = Info.createHeapAlloc(E, AllocType, Result);
*Val = APValue(APValue::UninitArray(), 0, Size.getZExtValue());
Result.addArray(Info, E, cast<ConstantArrayType>(AllocType));
@ -8561,7 +8561,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
ResizedArrayILE = cast<InitListExpr>(Init);
}
AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound,
AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound, nullptr,
ArrayType::Normal, 0);
} else {
assert(!AllocType->isArrayType() &&

View File

@ -109,6 +109,33 @@ bool QualType::isConstant(QualType T, const ASTContext &Ctx) {
return T.getAddressSpace() == LangAS::opencl_constant;
}
// C++ [temp.dep.type]p1:
// A type is dependent if it is...
// - an array type constructed from any dependent type or whose
// size is specified by a constant expression that is
// value-dependent,
ArrayType::ArrayType(TypeClass tc, QualType et, QualType can,
ArraySizeModifier sm, unsigned tq, const Expr *sz)
// Note, we need to check for DependentSizedArrayType explicitly here
// because we use a DependentSizedArrayType with no size expression as the
// type of a dependent array of unknown bound with a dependent braced
// initializer:
//
// template<int ...N> int arr[] = {N...};
: Type(tc, can,
et->isDependentType() || (sz && sz->isValueDependent()) ||
tc == DependentSizedArray,
et->isInstantiationDependentType() ||
(sz && sz->isInstantiationDependent()) ||
tc == DependentSizedArray,
(tc == VariableArray || et->isVariablyModifiedType()),
et->containsUnexpandedParameterPack() ||
(sz && sz->containsUnexpandedParameterPack())),
ElementType(et) {
ArrayTypeBits.IndexTypeQuals = tq;
ArrayTypeBits.SizeModifier = sm;
}
unsigned ConstantArrayType::getNumAddressingBits(const ASTContext &Context,
QualType ElementType,
const llvm::APInt &NumElements) {
@ -156,14 +183,26 @@ unsigned ConstantArrayType::getMaxSizeBits(const ASTContext &Context) {
return Bits;
}
void ConstantArrayType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context, QualType ET,
const llvm::APInt &ArraySize,
const Expr *SizeExpr, ArraySizeModifier SizeMod,
unsigned TypeQuals) {
ID.AddPointer(ET.getAsOpaquePtr());
ID.AddInteger(ArraySize.getZExtValue());
ID.AddInteger(SizeMod);
ID.AddInteger(TypeQuals);
ID.AddBoolean(SizeExpr != 0);
if (SizeExpr)
SizeExpr->Profile(ID, Context, true);
}
DependentSizedArrayType::DependentSizedArrayType(const ASTContext &Context,
QualType et, QualType can,
Expr *e, ArraySizeModifier sm,
unsigned tq,
SourceRange brackets)
: ArrayType(DependentSizedArray, et, can, sm, tq,
(et->containsUnexpandedParameterPack() ||
(e && e->containsUnexpandedParameterPack()))),
: ArrayType(DependentSizedArray, et, can, sm, tq, e),
Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
@ -860,7 +899,7 @@ public:
if (elementType.getAsOpaquePtr() == T->getElementType().getAsOpaquePtr())
return QualType(T, 0);
return Ctx.getConstantArrayType(elementType, T->getSize(),
return Ctx.getConstantArrayType(elementType, T->getSize(), T->getSizeExpr(),
T->getSizeModifier(),
T->getIndexTypeCVRQualifiers());
}
@ -3590,6 +3629,7 @@ static CachedProperties computeCachedProperties(const Type *T) {
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class:
#include "clang/AST/TypeNodes.inc"
// Treat instantiation-dependent types as external.
if (!T->isInstantiationDependentType()) T->dump();
assert(T->isInstantiationDependentType());
return CachedProperties(ExternalLinkage, false);

View File

@ -102,8 +102,9 @@ namespace {
llvm::APInt Size(
/*numBits=*/32,
C.toCharUnitsFromBits(AtomicSizeInBits).getQuantity());
AtomicTy = C.getConstantArrayType(C.CharTy, Size, ArrayType::Normal,
/*IndexTypeQuals=*/0);
AtomicTy =
C.getConstantArrayType(C.CharTy, Size, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
}
AtomicAlign = ValueAlign = lvalue.getAlignment();
} else if (lvalue.isVectorElt()) {

View File

@ -3791,7 +3791,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
-> std::tuple<llvm::Value *, llvm::Value *, llvm::Value *> {
llvm::APInt ArraySize(32, NumArgs - First);
QualType SizeArrayTy = getContext().getConstantArrayType(
getContext().getSizeType(), ArraySize, ArrayType::Normal,
getContext().getSizeType(), ArraySize, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
auto Tmp = CreateMemTemp(SizeArrayTy, "block_sizes");
llvm::Value *TmpPtr = Tmp.getPointer();

View File

@ -3276,8 +3276,8 @@ void CGDebugInfo::collectVarDeclProps(const VarDecl *VD, llvm::DIFile *&Unit,
llvm::APInt ConstVal(32, 1);
QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
T = CGM.getContext().getConstantArrayType(ET, ConstVal, ArrayType::Normal,
0);
T = CGM.getContext().getConstantArrayType(ET, ConstVal, nullptr,
ArrayType::Normal, 0);
}
Name = VD->getName();
@ -3873,8 +3873,8 @@ CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
if (NumPaddingBytes.isPositive()) {
llvm::APInt pad(32, NumPaddingBytes.getQuantity());
FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
pad, ArrayType::Normal, 0);
FType = CGM.getContext().getConstantArrayType(
CGM.getContext().CharTy, pad, nullptr, ArrayType::Normal, 0);
EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
}
}

View File

@ -143,7 +143,7 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
NumElements);
QualType ElementType = Context.getObjCIdType().withConst();
QualType ElementArrayType
= Context.getConstantArrayType(ElementType, APNumElements,
= Context.getConstantArrayType(ElementType, APNumElements, nullptr,
ArrayType::Normal, /*IndexTypeQuals=*/0);
// Allocate the temporary array(s).
@ -1661,7 +1661,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
QualType ItemsTy =
getContext().getConstantArrayType(getContext().getObjCIdType(),
llvm::APInt(32, NumItems),
llvm::APInt(32, NumItems), nullptr,
ArrayType::Normal, 0);
Address ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");

View File

@ -3376,9 +3376,9 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
// <copy_func>, did_it);
if (DidIt.isValid()) {
llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
QualType CopyprivateArrayTy =
C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
/*IndexTypeQuals=*/0);
QualType CopyprivateArrayTy = C.getConstantArrayType(
C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
// Create a list of all private variables for copyprivate.
Address CopyprivateList =
CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
@ -5362,7 +5362,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
// Define type kmp_depend_info[<Dependences.size()>];
QualType KmpDependInfoArrayTy = C.getConstantArrayType(
KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
ArrayType::Normal, /*IndexTypeQuals=*/0);
nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
// kmp_depend_info[<Dependences.size()>] deps;
DependenciesArray =
CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
@ -5883,7 +5883,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
}
llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
QualType ReductionArrayTy =
C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
Address ReductionList =
CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
@ -6355,7 +6355,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
unsigned Size = Data.ReductionVars.size();
llvm::APInt ArraySize(/*numBits=*/64, Size);
QualType ArrayRDType = C.getConstantArrayType(
RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
// kmp_task_red_input_t .rd_input.[Size];
Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
@ -8711,9 +8711,9 @@ emitOffloadingArrays(CodeGenFunction &CGF,
}
llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
QualType PointerArrayType =
Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
/*IndexTypeQuals=*/0);
QualType PointerArrayType = Ctx.getConstantArrayType(
Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
Info.BasePointersArray =
CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
@ -8726,9 +8726,9 @@ emitOffloadingArrays(CodeGenFunction &CGF,
QualType Int64Ty =
Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
if (hasRuntimeEvaluationCaptureSize) {
QualType SizeArrayType =
Ctx.getConstantArrayType(Int64Ty, PointerNumAP, ArrayType::Normal,
/*IndexTypeQuals=*/0);
QualType SizeArrayType = Ctx.getConstantArrayType(
Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
Info.SizesArray =
CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
} else {
@ -10967,7 +10967,7 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
}
llvm::APInt Size(/*numBits=*/32, NumIterations.size());
QualType ArrayTy =
C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
CGF.EmitNullInitialization(DimsAddr, ArrayTy);
@ -11018,7 +11018,7 @@ void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
QualType ArrayTy = CGM.getContext().getConstantArrayType(
Int64Ty, Size, ArrayType::Normal, 0);
Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
const Expr *CounterVal = C->getLoopData(I);

View File

@ -280,7 +280,8 @@ static RecordDecl *buildRecordForGlobalizedVars(
}
} else {
llvm::APInt ArraySize(32, BufSize);
Type = C.getConstantArrayType(Type, ArraySize, ArrayType::Normal, 0);
Type = C.getConstantArrayType(Type, ArraySize, nullptr, ArrayType::Normal,
0);
Field = FieldDecl::Create(
C, GlobalizedRD, Loc, Loc, VD->getIdentifier(), Type,
C.getTrivialTypeSourceInfo(Type, SourceLocation()),
@ -4269,7 +4270,7 @@ void CGOpenMPRuntimeNVPTX::emitReduction(
}
llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
QualType ReductionArrayTy =
C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
Address ReductionList =
CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
@ -5056,7 +5057,7 @@ void CGOpenMPRuntimeNVPTX::clear() {
Size = llvm::alignTo(Size, RecAlignment);
llvm::APInt ArySize(/*numBits=*/64, Size);
QualType SubTy = C.getConstantArrayType(
C.CharTy, ArySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
C.CharTy, ArySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
const bool UseSharedMemory = Size <= SharedMemorySize;
auto *Field =
FieldDecl::Create(C, UseSharedMemory ? SharedStaticRD : StaticRD,
@ -5083,7 +5084,7 @@ void CGOpenMPRuntimeNVPTX::clear() {
if (!SharedStaticRD->field_empty()) {
llvm::APInt ArySize(/*numBits=*/64, SharedMemorySize);
QualType SubTy = C.getConstantArrayType(
C.CharTy, ArySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
C.CharTy, ArySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
auto *Field = FieldDecl::Create(
C, SharedStaticRD, SourceLocation(), SourceLocation(), nullptr, SubTy,
C.getTrivialTypeSourceInfo(SubTy, SourceLocation()),
@ -5116,11 +5117,12 @@ void CGOpenMPRuntimeNVPTX::clear() {
std::pair<unsigned, unsigned> SMsBlockPerSM = getSMsBlocksPerSM(CGM);
llvm::APInt Size1(32, SMsBlockPerSM.second);
QualType Arr1Ty =
C.getConstantArrayType(StaticTy, Size1, ArrayType::Normal,
C.getConstantArrayType(StaticTy, Size1, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
llvm::APInt Size2(32, SMsBlockPerSM.first);
QualType Arr2Ty = C.getConstantArrayType(Arr1Ty, Size2, ArrayType::Normal,
/*IndexTypeQuals=*/0);
QualType Arr2Ty =
C.getConstantArrayType(Arr1Ty, Size2, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
llvm::Type *LLVMArr2Ty = CGM.getTypes().ConvertTypeForMem(Arr2Ty);
// FIXME: nvlink does not handle weak linkage correctly (object with the
// different size are reported as erroneous).

View File

@ -3158,7 +3158,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
getContext(), getContext().getTranslationUnitDecl(), /*NumParams=*/0);
llvm::APInt ArrSize(/*numBits=*/32, InputInfo.NumberOfTargetItems);
QualType BaseAndPointersType = getContext().getConstantArrayType(
getContext().VoidPtrTy, ArrSize, ArrayType::Normal,
getContext().VoidPtrTy, ArrSize, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
BPVD = createImplicitFirstprivateForType(
getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
@ -3166,7 +3166,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
QualType SizesType = getContext().getConstantArrayType(
getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1),
ArrSize, ArrayType::Normal,
ArrSize, nullptr, ArrayType::Normal,
/*IndexTypeQuals=*/0);
SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD,
S.getBeginLoc());

View File

@ -4771,7 +4771,7 @@ QualType CodeGenModule::getObjCFastEnumerationStateType() {
Context.getPointerType(Context.getObjCIdType()),
Context.getPointerType(Context.UnsignedLongTy),
Context.getConstantArrayType(Context.UnsignedLongTy,
llvm::APInt(32, 5), ArrayType::Normal, 0)
llvm::APInt(32, 5), nullptr, ArrayType::Normal, 0)
};
for (size_t i = 0; i < 4; ++i) {

View File

@ -597,8 +597,8 @@ namespace {
StringLiteral *getStringLiteral(StringRef Str) {
QualType StrType = Context->getConstantArrayType(
Context->CharTy, llvm::APInt(32, Str.size() + 1), ArrayType::Normal,
0);
Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,
ArrayType::Normal, 0);
return StringLiteral::Create(*Context, Str, StringLiteral::Ascii,
/*Pascal=*/false, StrType, SourceLocation());
}

View File

@ -497,8 +497,8 @@ namespace {
StringLiteral *getStringLiteral(StringRef Str) {
QualType StrType = Context->getConstantArrayType(
Context->CharTy, llvm::APInt(32, Str.size() + 1), ArrayType::Normal,
0);
Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,
ArrayType::Normal, 0);
return StringLiteral::Create(*Context, Str, StringLiteral::Ascii,
/*Pascal=*/false, StrType, SourceLocation());
}

View File

@ -1111,8 +1111,8 @@ void Sema::ActOnEndOfTranslationUnit() {
// Set the length of the array to 1 (C99 6.9.2p5).
Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
One, ArrayType::Normal, 0);
QualType T = Context.getConstantArrayType(ArrayT->getElementType(), One,
nullptr, ArrayType::Normal, 0);
VD->setType(T);
} else if (RequireCompleteType(VD->getLocation(), VD->getType(),
diag::err_tentative_def_incomplete_type))

View File

@ -5758,8 +5758,8 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
return QualType();
}
return Context.getConstantArrayType(VLATy->getElementType(),
Res, ArrayType::Normal, 0);
return Context.getConstantArrayType(
VLATy->getElementType(), Res, VLATy->getSizeExpr(), ArrayType::Normal, 0);
}
static void

View File

@ -3207,13 +3207,15 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
SmallString<32> RawChars;
ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
Str, RawChars);
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
ResTy = Context.getConstantArrayType(ResTy, LengthI, nullptr,
ArrayType::Normal,
/*IndexTypeQuals*/ 0);
SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide,
/*Pascal*/ false, ResTy, Loc);
} else {
ResTy = Context.adjustStringLiteralBaseType(Context.CharTy.withConst());
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
ResTy = Context.getConstantArrayType(ResTy, LengthI, nullptr,
ArrayType::Normal,
/*IndexTypeQuals*/ 0);
SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
/*Pascal*/ false, ResTy, Loc);
@ -3453,7 +3455,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
unsigned Length = Literal.getUDSuffixOffset();
QualType StrTy = Context.getConstantArrayType(
Context.adjustStringLiteralBaseType(Context.CharTy.withConst()),
llvm::APInt(32, Length + 1), ArrayType::Normal, 0);
llvm::APInt(32, Length + 1), nullptr, ArrayType::Normal, 0);
Expr *Lit = StringLiteral::Create(
Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii,
/*Pascal*/false, StrTy, &TokLoc, 1);

View File

@ -2111,9 +2111,10 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
QualType InitType;
if (KnownArraySize)
InitType = Context.getConstantArrayType(
AllocType, llvm::APInt(Context.getTypeSize(Context.getSizeType()),
*KnownArraySize),
ArrayType::Normal, 0);
AllocType,
llvm::APInt(Context.getTypeSize(Context.getSizeType()),
*KnownArraySize),
*ArraySize, ArrayType::Normal, 0);
else if (ArraySize)
InitType =
Context.getIncompleteArrayType(AllocType, ArrayType::Normal, 0);

View File

@ -67,7 +67,7 @@ ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType());
assert(CAT && "String literal not of constant array type!");
QualType StrTy = Context.getConstantArrayType(
CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1),
CAT->getElementType(), llvm::APInt(32, StrBuf.size() + 1), nullptr,
CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());
S = StringLiteral::Create(Context, StrBuf, StringLiteral::Ascii,
/*Pascal=*/false, StrTy, &StrLocs[0],

View File

@ -198,7 +198,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
llvm::APInt ConstVal(32, StrLength);
// Return a new array type (C99 6.7.8p22).
DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
ConstVal,
ConstVal, nullptr,
ArrayType::Normal, 0);
updateStringLiteralType(Str, DeclT);
return;
@ -1935,8 +1935,8 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
SemaRef.Diag(IList->getBeginLoc(), diag::ext_typecheck_zero_array_size);
}
DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements,
ArrayType::Normal, 0);
DeclType = SemaRef.Context.getConstantArrayType(
elementType, maxElements, nullptr, ArrayType::Normal, 0);
}
if (!hadError) {
// If there are any members of the array that get value-initialized, check
@ -3827,9 +3827,10 @@ static bool TryInitializerListConstruction(Sema &S,
// Try initializing a temporary array from the init list.
QualType ArrayType = S.Context.getConstantArrayType(
E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
List->getNumInits()),
clang::ArrayType::Normal, 0);
E.withConst(),
llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
List->getNumInits()),
nullptr, clang::ArrayType::Normal, 0);
InitializedEntity HiddenArray =
InitializedEntity::InitializeTemporary(ArrayType);
InitializationKind Kind = InitializationKind::CreateDirectList(
@ -8407,6 +8408,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
*ResultType = S.Context.getConstantArrayType(
IncompleteDest->getElementType(),
ConstantSource->getSize(),
ConstantSource->getSizeExpr(),
ArrayType::Normal, 0);
}
}
@ -8649,7 +8651,7 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
E.withConst(),
llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()),
InitList->getNumInits()),
clang::ArrayType::Normal, 0);
nullptr, clang::ArrayType::Normal, 0);
InitializedEntity HiddenArray =
InitializedEntity::InitializeTemporary(ArrayType);
return diagnoseListInit(S, HiddenArray, InitList);

View File

@ -13015,8 +13015,9 @@ static bool actOnOMPReductionKindClause(
// If we don't have a single element, we must emit a constant array type.
if (ConstantLengthOASE && !SingleElement) {
for (llvm::APSInt &Size : ArraySizes)
PrivateTy = Context.getConstantArrayType(
PrivateTy, Size, ArrayType::Normal, /*IndexTypeQuals=*/0);
PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
ArrayType::Normal,
/*IndexTypeQuals=*/0);
}
}

View File

@ -2290,7 +2290,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
}
}
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
T = Context.getConstantArrayType(T, ConstVal, ArraySize, ASM, Quals);
}
// OpenCL v1.2 s6.9.d: variable length arrays are not supported.

View File

@ -795,6 +795,7 @@ public:
QualType RebuildConstantArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
const llvm::APInt &Size,
Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange);
@ -4726,12 +4727,25 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
if (ElementType.isNull())
return QualType();
// Prefer the expression from the TypeLoc; the other may have been uniqued.
Expr *OldSize = TL.getSizeExpr();
if (!OldSize)
OldSize = const_cast<Expr*>(T->getSizeExpr());
Expr *NewSize = nullptr;
if (OldSize) {
EnterExpressionEvaluationContext Unevaluated(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
NewSize = getDerived().TransformExpr(OldSize).template getAs<Expr>();
NewSize = SemaRef.ActOnConstantExpression(NewSize).get();
}
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
ElementType != T->getElementType()) {
ElementType != T->getElementType() ||
(T->getSizeExpr() && NewSize != OldSize)) {
Result = getDerived().RebuildConstantArrayType(ElementType,
T->getSizeModifier(),
T->getSize(),
T->getSize(), NewSize,
T->getIndexTypeCVRQualifiers(),
TL.getBracketsRange());
if (Result.isNull())
@ -4745,15 +4759,7 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
NewTL.setLBracketLoc(TL.getLBracketLoc());
NewTL.setRBracketLoc(TL.getRBracketLoc());
Expr *Size = TL.getSizeExpr();
if (Size) {
EnterExpressionEvaluationContext Unevaluated(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
Size = getDerived().TransformExpr(Size).template getAs<Expr>();
Size = SemaRef.ActOnConstantExpression(Size).get();
}
NewTL.setSizeExpr(Size);
NewTL.setSizeExpr(NewSize);
return Result;
}
@ -12802,9 +12808,10 @@ QualType
TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
const llvm::APInt &Size,
Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, nullptr,
return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, SizeExpr,
IndexTypeQuals, BracketsRange);
}

View File

@ -6379,7 +6379,8 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
unsigned IndexTypeQuals = Record[2];
unsigned Idx = 3;
llvm::APInt Size = ReadAPInt(Record, Idx);
return Context.getConstantArrayType(ElementType, Size,
Expr *SizeExpr = ReadExpr(*Loc.F);
return Context.getConstantArrayType(ElementType, Size, SizeExpr,
ASM, IndexTypeQuals);
}

View File

@ -238,6 +238,7 @@ void ASTTypeWriter::VisitArrayType(const ArrayType *T) {
void ASTTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
VisitArrayType(T);
Record.AddAPInt(T->getSize());
Record.AddStmt(const_cast<Expr*>(T->getSizeExpr()));
Code = TYPE_CONSTANT_ARRAY;
}

View File

@ -24,7 +24,7 @@ struct __declspec(uuid("EAFA1952-66F8-438B-8FBA-AF1BBAE42191")) TestStruct
template <class T> void test_uuidofType(void *arg[sizeof(__uuidof(T))] = 0) {}
template <class T> void test_uuidofExpr(void *arg[sizeof(__uuidof(T::member))] = 0) {}
template <class T> void test_uuidofExpr(void *arg[sizeof(__uuidof(typename T::member))] = 0) {}
struct HasMember { typedef TestStruct member; };

View File

@ -488,9 +488,8 @@ namespace instantiation_dependent {
template<typename T, __typeof(sizeof(0))> int &f(...);
int &rf = f<struct incomplete, 0>(0);
// FIXME: This fails because we mishandle instantiation-dependent array bounds :(
int arr[sizeof(sizeof(int))];
template<typename T, int (*)[sizeof(sizeof(T))]> void g(int);
template<typename T, int (*)[sizeof(sizeof(int))]> int &g(...);
int &rg = g<struct incomplete, &arr>(0); // expected-error {{cannot bind}}
int &rg = g<struct incomplete, &arr>(0);
}

View File

@ -2180,7 +2180,7 @@ CompilerType ClangASTContext::CreateArrayType(const CompilerType &element_type,
} else {
return CompilerType(this, ast->getConstantArrayType(
ClangUtil::GetQualType(element_type),
ap_element_count,
ap_element_count, nullptr,
clang::ArrayType::Normal, 0)
.getAsOpaquePtr());
}
@ -4469,7 +4469,7 @@ CompilerType ClangASTContext::GetArrayType(lldb::opaque_compiler_type_t type,
return CompilerType(
this, ast_ctx
->getConstantArrayType(
qual_type, llvm::APInt(64, size),
qual_type, llvm::APInt(64, size), nullptr,
clang::ArrayType::ArraySizeModifier::Normal, 0)
.getAsOpaquePtr());
else