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;
/// 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;
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())); })
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;
union {
TypeBitfields TypeBits;
ArrayTypeBitfields ArrayTypeBits;
+ ConstantArrayTypeBitfields ConstantArrayTypeBits;
AttributedTypeBitfields AttributedTypeBits;
AutoTypeBitfields AutoTypeBits;
BuiltinTypeBitfields BuiltinTypeBits;
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; }
/// 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) {}
-
-protected:
- friend class ASTContext; // ASTContext creates these.
+ 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;
+ }
+ }
- 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); }
/// 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;
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;
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:
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)),
/// 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);
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);
result = getConstantArrayType(
getVariableArrayDecayedType(cat->getElementType()),
cat->getSize(),
+ cat->getSizeExpr(),
cat->getSizeModifier(),
cat->getIndexTypeCVRQualifiers());
break;
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)) {
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))
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");
}
// 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");
}
// 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");
}
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))
// 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);
}
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
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));
ResizedArrayILE = cast<InitListExpr>(Init);
}
- AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound,
+ AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound, nullptr,
ArrayType::Normal, 0);
} else {
assert(!AllocType->isArrayType() &&
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) {
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,
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());
}
#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);
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()) {
-> 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();
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();
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));
}
}
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).
QualType ItemsTy =
getContext().getConstantArrayType(getContext().getObjCIdType(),
- llvm::APInt(32, NumItems),
+ llvm::APInt(32, NumItems), nullptr,
ArrayType::Normal, 0);
Address ItemsPtr = CreateMemTemp(ItemsTy, "items.ptr");
// <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");
// 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");
}
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");
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,
}
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();
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 {
}
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);
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);
}
} 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()),
}
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");
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,
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()),
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).
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());
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());
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) {
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());
}
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());
}
// 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))
return QualType();
}
- return Context.getConstantArrayType(VLATy->getElementType(),
- Res, ArrayType::Normal, 0);
+ return Context.getConstantArrayType(
+ VLATy->getElementType(), Res, VLATy->getSizeExpr(), ArrayType::Normal, 0);
}
static void
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);
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);
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);
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],
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;
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
// 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(
*ResultType = S.Context.getConstantArrayType(
IncompleteDest->getElementType(),
ConstantSource->getSize(),
+ ConstantSource->getSizeExpr(),
ArrayType::Normal, 0);
}
}
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);
// 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);
}
}
}
}
- 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.
QualType RebuildConstantArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
const llvm::APInt &Size,
+ Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange);
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())
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;
}
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);
}
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);
}
void ASTTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
VisitArrayType(T);
Record.AddAPInt(T->getSize());
+ Record.AddStmt(const_cast<Expr*>(T->getSizeExpr()));
Code = TYPE_CONSTANT_ARRAY;
}
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; };
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);
}