Newer
Older
//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for initializers. The main entry
// point is Sema::CheckInitList(), but all of the work is performed
// within the InitListChecker class.
//
// This file also implements Sema::CheckInitializerTypes.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "clang/Parse/Designator.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExprObjC.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// Sema Initialization Checking
//===----------------------------------------------------------------------===//
static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
const ArrayType *AT = Context.getAsArrayType(DeclType);
if (!AT) return 0;
// See if this is a string literal or @encode.
Init = Init->IgnoreParens();
// Handle @encode, which is a narrow string.
if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType())
return Init;
// Otherwise we can only handle string literals.
StringLiteral *SL = dyn_cast<StringLiteral>(Init);
// char array can be initialized with a narrow string.
// Only allow char x[] = "foo"; not char x[] = L"foo";
if (!SL->isWide())
return AT->getElementType()->isCharType() ? Init : 0;
// wchar_t array can be initialized with a wide string: C99 6.7.8p15:
// "An array with element type compatible with wchar_t may be initialized by a
// wide string literal, optionally enclosed in braces."
if (Context.typesAreCompatible(Context.getWCharType(), AT->getElementType()))
// Only allow wchar_t x[] = L"foo"; not wchar_t x[] = "foo";
return Init;
return 0;
}
static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
bool DirectInit, Sema &S) {
// Get the type before calling CheckSingleAssignmentConstraints(), since
// it can promote the expression.
QualType InitType = Init->getType();
if (S.getLangOptions().CPlusPlus) {
// FIXME: I dislike this error message. A lot.
if (S.PerformImplicitConversion(Init, DeclType, "initializing", DirectInit))
return S.Diag(Init->getSourceRange().getBegin(),
diag::err_typecheck_convert_incompatible)
<< DeclType << Init->getType() << "initializing"
<< Init->getSourceRange();
return false;
}
Sema::AssignConvertType ConvTy =
S.CheckSingleAssignmentConstraints(DeclType, Init);
return S.DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
InitType, Init, "initializing");
}
static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
// Get the length of the string as parsed.
uint64_t StrLength =
cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue();
const ArrayType *AT = S.Context.getAsArrayType(DeclT);
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
// C99 6.7.8p14. We have an array of character type with unknown size
// being initialized to a string literal.
llvm::APSInt ConstVal(32);
ConstVal = StrLength;
// Return a new array type (C99 6.7.8p22).
DeclT = S.Context.getConstantArrayType(IAT->getElementType(), ConstVal,
ArrayType::Normal, 0);
const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
// C99 6.7.8p14. We have an array of character type with known size. However,
// the size may be smaller or larger than the string we are initializing.
// FIXME: Avoid truncation for 64-bit length strings.
if (StrLength-1 > CAT->getSize().getZExtValue())
S.Diag(Str->getSourceRange().getBegin(),
diag::warn_initializer_string_for_char_array_too_long)
<< Str->getSourceRange();
// Set the type to the actual size that we are initializing. If we have
// something like:
// char x[1] = "foo";
// then this will set the string literal's type to char[1].
Str->setType(DeclT);
}
bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
SourceLocation InitLoc,
DeclarationName InitEntity,
bool DirectInit) {
if (DeclType->isDependentType() || Init->isTypeDependent())
return false;
// C++ [dcl.init.ref]p1:
// A variable declared to be a T& or T&&, that is "reference to type T"
// (8.3.2), shall be initialized by an object, or function, of
// type T or by an object that can be converted into a T.
if (DeclType->isReferenceType())
return CheckReferenceInit(Init, DeclType, 0, false, DirectInit);
// C99 6.7.8p3: The type of the entity to be initialized shall be an array
// of unknown size ("[]") or an object type that is not a variable array type.
if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType))
return Diag(InitLoc, diag::err_variable_object_no_init)
<< VAT->getSizeExpr()->getSourceRange();
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
if (!InitList) {
// FIXME: Handle wide strings
if (Expr *Str = IsStringInit(Init, DeclType, Context)) {
CheckStringInit(Str, DeclType, *this);
return false;
}
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// C++ [dcl.init]p14:
// -- If the destination type is a (possibly cv-qualified) class
// type:
if (getLangOptions().CPlusPlus && DeclType->isRecordType()) {
QualType DeclTypeC = Context.getCanonicalType(DeclType);
QualType InitTypeC = Context.getCanonicalType(Init->getType());
// -- If the initialization is direct-initialization, or if it is
// copy-initialization where the cv-unqualified version of the
// source type is the same class as, or a derived class of, the
// class of the destination, constructors are considered.
if ((DeclTypeC.getUnqualifiedType() == InitTypeC.getUnqualifiedType()) ||
IsDerivedFrom(InitTypeC, DeclTypeC)) {
CXXConstructorDecl *Constructor
= PerformInitializationByConstructor(DeclType, &Init, 1,
InitLoc, Init->getSourceRange(),
InitEntity,
DirectInit? IK_Direct : IK_Copy);
return Constructor == 0;
}
// -- Otherwise (i.e., for the remaining copy-initialization
// cases), user-defined conversion sequences that can
// convert from the source type to the destination type or
// (when a conversion function is used) to a derived class
// thereof are enumerated as described in 13.3.1.4, and the
// best one is chosen through overload resolution
// (13.3). If the conversion cannot be done or is
// ambiguous, the initialization is ill-formed. The
// function selected is called with the initializer
// expression as its argument; if the function is a
// constructor, the call initializes a temporary of the
// destination type.
// FIXME: We're pretending to do copy elision here; return to
// this when we have ASTs for such things.
if (!PerformImplicitConversion(Init, DeclType, "initializing"))
return false;
if (InitEntity)
return Diag(InitLoc, diag::err_cannot_initialize_decl)
<< InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
<< Init->getType() << Init->getSourceRange();
else
return Diag(InitLoc, diag::err_cannot_initialize_decl_noname)
<< DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
<< Init->getType() << Init->getSourceRange();
}
// C99 6.7.8p16.
if (DeclType->isArrayType())
return Diag(Init->getLocStart(), diag::err_array_init_list_required)
<< Init->getSourceRange();
return CheckSingleInitializer(Init, DeclType, DirectInit, *this);
}
bool hadError = CheckInitList(InitList, DeclType);
Init = InitList;
return hadError;
}
//===----------------------------------------------------------------------===//
// Semantic checking for initializer lists.
//===----------------------------------------------------------------------===//
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/// @brief Semantic checking for initializer lists.
///
/// The InitListChecker class contains a set of routines that each
/// handle the initialization of a certain kind of entity, e.g.,
/// arrays, vectors, struct/union types, scalars, etc. The
/// InitListChecker itself performs a recursive walk of the subobject
/// structure of the type to be initialized, while stepping through
/// the initializer list one element at a time. The IList and Index
/// parameters to each of the Check* routines contain the active
/// (syntactic) initializer list and the index into that initializer
/// list that represents the current initializer. Each routine is
/// responsible for moving that Index forward as it consumes elements.
///
/// Each Check* routine also has a StructuredList/StructuredIndex
/// arguments, which contains the current the "structured" (semantic)
/// initializer list and the index into that initializer list where we
/// are copying initializers as we map them over to the semantic
/// list. Once we have completed our recursive walk of the subobject
/// structure, we will have constructed a full semantic initializer
/// list.
///
/// C99 designators cause changes in the initializer list traversal,
/// because they make the initialization "jump" into a specific
/// subobject and then continue the initialization from that
/// point. CheckDesignatedInitializer() recursively steps into the
/// designated subobject and manages backing out the recursion to
/// initialize the subobjects after the one designated.
bool hadError;
std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
InitListExpr *FullyStructuredList;
void CheckImplicitInitList(InitListExpr *ParentIList, QualType T,
unsigned &Index, InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject = false);
void CheckExplicitInitList(InitListExpr *IList, QualType &T,
unsigned &Index, InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject = false);
void CheckListElementTypes(InitListExpr *IList, QualType &DeclType,
bool SubobjectIsDesignatorContext,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject = false);
void CheckSubElementType(InitListExpr *IList, QualType ElemType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
void CheckScalarType(InitListExpr *IList, QualType DeclType,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
void CheckReferenceType(InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
void CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
void CheckStructUnionTypes(InitListExpr *IList, QualType DeclType,
RecordDecl::field_iterator Field,
bool SubobjectIsDesignatorContext, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject = false);
void CheckArrayType(InitListExpr *IList, QualType &DeclType,
llvm::APSInt elementIndex,
bool SubobjectIsDesignatorContext, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
bool CheckDesignatedInitializer(InitListExpr *IList, DesignatedInitExpr *DIE,
DesignatedInitExpr::designators_iterator D,
QualType &CurrentObjectType,
RecordDecl::field_iterator *NextField,
llvm::APSInt *NextElementIndex,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool FinishSubobjectInit,
bool TopLevelObject);
InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
QualType CurrentObjectType,
InitListExpr *StructuredList,
unsigned StructuredIndex,
SourceRange InitRange);
void UpdateStructuredListElement(InitListExpr *StructuredList,
unsigned &StructuredIndex,
Expr *expr);
int numArrayElements(QualType DeclType);
int numStructUnionElements(QualType DeclType);
void FillInValueInitializations(InitListExpr *ILE);
InitListChecker(Sema &S, InitListExpr *IL, QualType &T);
bool HadError() { return hadError; }
// @brief Retrieves the fully-structured initializer list used for
// semantic analysis and code generation.
InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
};
} // end anonymous namespace
/// Recursively replaces NULL values within the given initializer list
/// with expressions that perform value-initialization of the
/// appropriate type.
void InitListChecker::FillInValueInitializations(InitListExpr *ILE) {
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
"Should not have void type");
SourceLocation Loc = ILE->getSourceRange().getBegin();
if (ILE->getSyntacticForm())
Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
if (const RecordType *RType = ILE->getType()->getAsRecordType()) {
unsigned Init = 0, NumInits = ILE->getNumInits();
for (RecordDecl::field_iterator
Field = RType->getDecl()->field_begin(SemaRef.Context),
FieldEnd = RType->getDecl()->field_end(SemaRef.Context);
Field != FieldEnd; ++Field) {
if (Field->isUnnamedBitfield())
continue;
if (Init >= NumInits || !ILE->getInit(Init)) {
if (Field->getType()->isReferenceType()) {
// C++ [dcl.init.aggr]p9:
// If an incomplete or empty initializer-list leaves a
// member of reference type uninitialized, the program is
// ill-formed.
SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
<< Field->getType()
<< ILE->getSyntacticForm()->getSourceRange();
SemaRef.Diag(Field->getLocation(),
diag::note_uninit_reference_member);
hadError = true;
return;
} else if (SemaRef.CheckValueInitialization(Field->getType(), Loc)) {
hadError = true;
return;
// FIXME: If value-initialization involves calling a
// constructor, should we make that call explicit in the
// representation (even when it means extending the
// initializer list)?
if (Init < NumInits && !hadError)
ILE->setInit(Init,
new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()));
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
FillInValueInitializations(InnerILE);
// Only look at the first initialization of a union.
if (RType->getDecl()->isUnion())
break;
}
return;
}
QualType ElementType;
unsigned NumInits = ILE->getNumInits();
unsigned NumElements = NumInits;
if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
ElementType = AType->getElementType();
if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
NumElements = CAType->getSize().getZExtValue();
} else if (const VectorType *VType = ILE->getType()->getAsVectorType()) {
ElementType = VType->getElementType();
NumElements = VType->getNumElements();
} else
ElementType = ILE->getType();
for (unsigned Init = 0; Init != NumElements; ++Init) {
if (Init >= NumInits || !ILE->getInit(Init)) {
if (SemaRef.CheckValueInitialization(ElementType, Loc)) {
hadError = true;
return;
}
// FIXME: If value-initialization involves calling a
// constructor, should we make that call explicit in the
// representation (even when it means extending the
// initializer list)?
if (Init < NumInits && !hadError)
ILE->setInit(Init,
new (SemaRef.Context) ImplicitValueInitExpr(ElementType));
else if (InitListExpr *InnerILE =dyn_cast<InitListExpr>(ILE->getInit(Init)))
FillInValueInitializations(InnerILE);
InitListChecker::InitListChecker(Sema &S, InitListExpr *IL, QualType &T)
: SemaRef(S) {
hadError = false;
unsigned newIndex = 0;
unsigned newStructuredIndex = 0;
FullyStructuredList
= getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex,
/*TopLevelObject=*/true);
if (!hadError)
FillInValueInitializations(FullyStructuredList);
}
int InitListChecker::numArrayElements(QualType DeclType) {
// FIXME: use a proper constant
int maxElements = 0x7FFFFFFF;
SemaRef.Context.getAsConstantArrayType(DeclType)) {
maxElements = static_cast<int>(CAT->getSize().getZExtValue());
}
return maxElements;
}
int InitListChecker::numStructUnionElements(QualType DeclType) {
RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl();
int InitializableMembers = 0;
for (RecordDecl::field_iterator
Field = structDecl->field_begin(SemaRef.Context),
FieldEnd = structDecl->field_end(SemaRef.Context);
Field != FieldEnd; ++Field) {
if ((*Field)->getIdentifier() || !(*Field)->isBitField())
++InitializableMembers;
}
return std::min(InitializableMembers, 1);
return InitializableMembers - structDecl->hasFlexibleArrayMember();
}
void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList,
QualType T, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject) {
int maxElements = 0;
if (T->isArrayType())
maxElements = numArrayElements(T);
else if (T->isStructureType() || T->isUnionType())
maxElements = numStructUnionElements(T);
else if (T->isVectorType())
maxElements = T->getAsVectorType()->getNumElements();
else
assert(0 && "CheckImplicitInitList(): Illegal type");
if (maxElements == 0) {
SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
diag::err_implicit_empty_initializer);
hadError = true;
return;
}
// Build a structured initializer list corresponding to this subobject.
InitListExpr *StructuredSubobjectInitList
= getStructuredSubobjectInit(ParentIList, Index, T, StructuredList,
StructuredIndex,
SourceRange(ParentIList->getInit(Index)->getSourceRange().getBegin(),
ParentIList->getSourceRange().getEnd()));
unsigned StructuredSubobjectInitIndex = 0;
// Check the element types and build the structural subobject.
unsigned StartIndex = Index;
CheckListElementTypes(ParentIList, T, false, Index,
StructuredSubobjectInitList,
StructuredSubobjectInitIndex,
TopLevelObject);
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
StructuredSubobjectInitList->setType(T);
// Update the structured sub-object initializer so that it's ending
// range corresponds with the end of the last initializer it used.
if (EndIndex < ParentIList->getNumInits()) {
SourceLocation EndLoc
= ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
StructuredSubobjectInitList->setRBraceLoc(EndLoc);
}
Steve Naroff
committed
void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject) {
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
SyntacticToSemantic[IList] = StructuredList;
StructuredList->setSyntacticForm(IList);
CheckListElementTypes(IList, T, true, Index, StructuredList,
StructuredIndex, TopLevelObject);
Steve Naroff
committed
IList->setType(T);
StructuredList->setType(T);
if (hadError)
return;
if (Index < IList->getNumInits()) {
// We have leftover initializers
if (IList->getNumInits() > 0 &&
IsStringInit(IList->getInit(Index), T, SemaRef.Context)) {
unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
if (SemaRef.getLangOptions().CPlusPlus)
DK = diag::err_excess_initializers_in_char_array_initializer;
// Special-case
SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
<< IList->getInit(Index)->getSourceRange();
} else if (!T->isIncompleteType()) {
// Don't complain for incomplete types, since we'll get an error
// elsewhere
QualType CurrentObjectType = StructuredList->getType();
int initKind =
CurrentObjectType->isArrayType()? 0 :
CurrentObjectType->isVectorType()? 1 :
CurrentObjectType->isScalarType()? 2 :
CurrentObjectType->isUnionType()? 3 :
4;
unsigned DK = diag::warn_excess_initializers;
if (SemaRef.getLangOptions().CPlusPlus)
DK = diag::err_excess_initializers;
SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
<< initKind << IList->getInit(Index)->getSourceRange();
if (T->isScalarType())
SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
<< IList->getSourceRange()
<< CodeModificationHint::CreateRemoval(SourceRange(IList->getLocStart()))
<< CodeModificationHint::CreateRemoval(SourceRange(IList->getLocEnd()));
void InitListChecker::CheckListElementTypes(InitListExpr *IList,
QualType &DeclType,
bool SubobjectIsDesignatorContext,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject) {
Douglas Gregor
committed
CheckScalarType(IList, DeclType, Index, StructuredList, StructuredIndex);
CheckVectorType(IList, DeclType, Index, StructuredList, StructuredIndex);
} else if (DeclType->isAggregateType()) {
if (DeclType->isRecordType()) {
RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
CheckStructUnionTypes(IList, DeclType, RD->field_begin(SemaRef.Context),
SubobjectIsDesignatorContext, Index,
StructuredList, StructuredIndex,
TopLevelObject);
} else if (DeclType->isArrayType()) {
llvm::APSInt Zero(
SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
false);
CheckArrayType(IList, DeclType, Zero, SubobjectIsDesignatorContext, Index,
StructuredList, StructuredIndex);
assert(0 && "Aggregate that isn't a structure or array?!");
Steve Naroff
committed
} else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
// This type is invalid, issue a diagnostic.
SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
<< DeclType;
} else if (DeclType->isRecordType()) {
// C++ [dcl.init]p14:
// [...] If the class is an aggregate (8.5.1), and the initializer
// is a brace-enclosed list, see 8.5.1.
//
// Note: 8.5.1 is handled below; here, we diagnose the case where
// we have an initializer list and a destination type that is not
// an aggregate.
// FIXME: In C++0x, this is yet another form of initialization.
SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
<< DeclType << IList->getSourceRange();
hadError = true;
} else if (DeclType->isReferenceType()) {
CheckReferenceType(IList, DeclType, Index, StructuredList, StructuredIndex);
} else {
// In C, all types are either scalars or aggregates, but
// additional handling is needed here for C++ (and possibly others?).
assert(0 && "Unsupported initializer type");
}
}
void InitListChecker::CheckSubElementType(InitListExpr *IList,
QualType ElemType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
Douglas Gregor
committed
Expr *expr = IList->getInit(Index);
if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
unsigned newIndex = 0;
unsigned newStructuredIndex = 0;
InitListExpr *newStructuredList
= getStructuredSubobjectInit(IList, Index, ElemType,
StructuredList, StructuredIndex,
SubInitList->getSourceRange());
CheckExplicitInitList(SubInitList, ElemType, newIndex,
newStructuredList, newStructuredIndex);
++StructuredIndex;
++Index;
} else if (Expr *Str = IsStringInit(expr, ElemType, SemaRef.Context)) {
CheckStringInit(Str, ElemType, SemaRef);
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
Douglas Gregor
committed
CheckScalarType(IList, ElemType, Index, StructuredList, StructuredIndex);
} else if (ElemType->isReferenceType()) {
CheckReferenceType(IList, ElemType, Index, StructuredList, StructuredIndex);
} else {
if (SemaRef.getLangOptions().CPlusPlus) {
// C++ [dcl.init.aggr]p12:
// All implicit type conversions (clause 4) are considered when
// initializing the aggregate member with an ini- tializer from
// an initializer-list. If the initializer can initialize a
// member, the member is initialized. [...]
ImplicitConversionSequence ICS
= SemaRef.TryCopyInitialization(expr, ElemType);
if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion) {
if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS,
"initializing"))
hadError = true;
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
return;
}
// Fall through for subaggregate initialization
} else {
// C99 6.7.8p13:
//
// The initializer for a structure or union object that has
// automatic storage duration shall be either an initializer
// list as described below, or a single expression that has
// compatible structure or union type. In the latter case, the
// initial value of the object, including unnamed members, is
// that of the expression.
QualType ExprType = SemaRef.Context.getCanonicalType(expr->getType());
QualType ElemTypeCanon = SemaRef.Context.getCanonicalType(ElemType);
if (SemaRef.Context.typesAreCompatible(ExprType.getUnqualifiedType(),
ElemTypeCanon.getUnqualifiedType())) {
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
return;
}
// Fall through for subaggregate initialization
}
// C++ [dcl.init.aggr]p12:
//
// [...] Otherwise, if the member is itself a non-empty
// subaggregate, brace elision is assumed and the initializer is
// considered for the initialization of the first member of
// the subaggregate.
if (ElemType->isAggregateType() || ElemType->isVectorType()) {
CheckImplicitInitList(IList, ElemType, Index, StructuredList,
StructuredIndex);
++StructuredIndex;
} else {
// We cannot initialize this element, so let
// PerformCopyInitialization produce the appropriate diagnostic.
SemaRef.PerformCopyInitialization(expr, ElemType, "initializing");
hadError = true;
++Index;
++StructuredIndex;
}
}
}
void InitListChecker::CheckScalarType(InitListExpr *IList, QualType DeclType,
Douglas Gregor
committed
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
if (Index < IList->getNumInits()) {
Douglas Gregor
committed
Expr *expr = IList->getInit(Index);
SemaRef.Diag(IList->getLocStart(),
diag::err_many_braces_around_scalar_init)
<< IList->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
return;
} else if (isa<DesignatedInitExpr>(expr)) {
SemaRef.Diag(expr->getSourceRange().getBegin(),
diag::err_designator_for_scalar_init)
<< DeclType << expr->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
if (CheckSingleInitializer(expr, DeclType, false, SemaRef))
hadError = true; // types weren't compatible.
else if (savExpr != expr) {
// The type was promoted, update initializer list.
Douglas Gregor
committed
IList->setInit(Index, expr);
if (hadError)
++StructuredIndex;
else
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
} else {
SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
hadError = true;
++Index;
++StructuredIndex;
return;
}
}
void InitListChecker::CheckReferenceType(InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
if (Index < IList->getNumInits()) {
Expr *expr = IList->getInit(Index);
if (isa<InitListExpr>(expr)) {
SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
<< DeclType << IList->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
return;
}
Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
if (SemaRef.CheckReferenceInit(expr, DeclType))
hadError = true;
else if (savExpr != expr) {
// The type was promoted, update initializer list.
IList->setInit(Index, expr);
}
if (hadError)
++StructuredIndex;
else
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
} else {
// FIXME: It would be wonderful if we could point at the actual
// member. In general, it would be useful to pass location
// information down the stack, so that we know the location (or
// decl) of the "current object" being initialized.
SemaRef.Diag(IList->getLocStart(),
diag::err_init_reference_member_uninitialized)
<< DeclType
<< IList->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
return;
}
}
void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
if (Index < IList->getNumInits()) {
const VectorType *VT = DeclType->getAsVectorType();
int maxElements = VT->getNumElements();
QualType elementType = VT->getElementType();
for (int i = 0; i < maxElements; ++i) {
// Don't attempt to go past the end of the init list
if (Index >= IList->getNumInits())
break;
Douglas Gregor
committed
CheckSubElementType(IList, elementType, Index,
StructuredList, StructuredIndex);
}
}
}
void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
llvm::APSInt elementIndex,
bool SubobjectIsDesignatorContext,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
// Check for the special-case of initializing an array with a string.
if (Index < IList->getNumInits()) {
if (Expr *Str = IsStringInit(IList->getInit(Index), DeclType,
SemaRef.Context)) {
CheckStringInit(Str, DeclType, SemaRef);
// We place the string literal directly into the resulting
// initializer list. This is the only place where the structure
// of the structured initializer list doesn't match exactly,
// because doing so would involve allocating one character
// constant for each string.
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
++Index;
return;
}
}
SemaRef.Context.getAsVariableArrayType(DeclType)) {
// Check for VLAs; in standard C it would be possible to check this
// earlier, but I don't know where clang accepts VLAs (gcc accepts
// them in all sorts of strange places).
SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
diag::err_variable_object_no_init)
<< VAT->getSizeExpr()->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
return;
}
// We might know the maximum number of elements in advance.
llvm::APSInt maxElements(elementIndex.getBitWidth(),
elementIndex.isUnsigned());
bool maxElementsKnown = false;
if (const ConstantArrayType *CAT =
SemaRef.Context.getAsConstantArrayType(DeclType)) {
maxElements = CAT->getSize();
elementIndex.extOrTrunc(maxElements.getBitWidth());
Douglas Gregor
committed
elementIndex.setIsUnsigned(maxElements.isUnsigned());
maxElementsKnown = true;
}
QualType elementType = SemaRef.Context.getAsArrayType(DeclType)
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
// If we're not the subobject that matches up with the '{' for
// the designator, we shouldn't be handling the
// designator. Return immediately.
if (!SubobjectIsDesignatorContext)
return;
// Handle this designated initializer. elementIndex will be
// updated to be the next array element we'll initialize.
if (CheckDesignatedInitializer(IList, DIE, DIE->designators_begin(),
DeclType, 0, &elementIndex, Index,
StructuredList, StructuredIndex, true,
false)) {
hadError = true;
continue;
}
if (elementIndex.getBitWidth() > maxElements.getBitWidth())
maxElements.extend(elementIndex.getBitWidth());
else if (elementIndex.getBitWidth() < maxElements.getBitWidth())
elementIndex.extend(maxElements.getBitWidth());
Douglas Gregor
committed
elementIndex.setIsUnsigned(maxElements.isUnsigned());
// If the array is of incomplete type, keep track of the number of
// elements in the initializer.
if (!maxElementsKnown && elementIndex > maxElements)
maxElements = elementIndex;
continue;
}
// If we know the maximum number of elements, and we've already
// hit it, stop consuming elements in the initializer list.
if (maxElementsKnown && elementIndex == maxElements)
// Check this element.
Douglas Gregor
committed
CheckSubElementType(IList, elementType, Index,
StructuredList, StructuredIndex);
++elementIndex;
// If the array is of incomplete type, keep track of the number of
// elements in the initializer.
if (!maxElementsKnown && elementIndex > maxElements)
maxElements = elementIndex;
}
if (DeclType->isIncompleteArrayType()) {
// If this is an incomplete array type, the actual type needs to
// be calculated here.
Douglas Gregor
committed
llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
if (maxElements == Zero) {
// Sizing an array implicitly to zero is not allowed by ISO C,
// but is supported by GNU.
SemaRef.Diag(IList->getLocStart(),
diag::ext_typecheck_zero_array_size);
DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements,
ArrayType::Normal, 0);
}
}
void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
QualType DeclType,
RecordDecl::field_iterator Field,
bool SubobjectIsDesignatorContext,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject) {
RecordDecl* structDecl = DeclType->getAsRecordType()->getDecl();
// If the record is invalid, some of it's members are invalid. To avoid
// confusion, we forgo checking the intializer for the entire record.
if (structDecl->isInvalidDecl()) {
hadError = true;
return;
}
if (DeclType->isUnionType() && IList->getNumInits() == 0) {
// Value-initialize the first named member of the union.
RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
for (RecordDecl::field_iterator FieldEnd = RD->field_end(SemaRef.Context);
Field != FieldEnd; ++Field) {
if (Field->getDeclName()) {
StructuredList->setInitializedFieldInUnion(*Field);
break;
}
}
return;
}
// If structDecl is a forward declaration, this loop won't do
// anything except look at designated initializers; That's okay,
// because an error should get printed out elsewhere. It might be
// worthwhile to skip over the rest of the initializer, though.
RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
RecordDecl::field_iterator FieldEnd = RD->field_end(SemaRef.Context);
bool InitializedSomething = false;
while (Index < IList->getNumInits()) {
Expr *Init = IList->getInit(Index);
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
// If we're not the subobject that matches up with the '{' for
// the designator, we shouldn't be handling the
// designator. Return immediately.
if (!SubobjectIsDesignatorContext)
return;
// Handle this designated initializer. Field will be updated to
// the next field that we'll be initializing.
if (CheckDesignatedInitializer(IList, DIE, DIE->designators_begin(),
DeclType, &Field, 0, Index,
StructuredList, StructuredIndex,
true, TopLevelObject))
hadError = true;
InitializedSomething = true;
continue;
}
if (Field == FieldEnd) {
// We've run out of fields. We're done.
break;
// We've already initialized a member of a union. We're done.
if (InitializedSomething && DeclType->isUnionType())
break;
// If we've hit the flexible array member at the end, we're done.
if (Field->getType()->isIncompleteArrayType())
break;
if (Field->isUnnamedBitfield()) {
// Don't initialize unnamed bitfields, e.g. "int : 20;"
continue;
Douglas Gregor
committed
CheckSubElementType(IList, Field->getType(), Index,
StructuredList, StructuredIndex);
InitializedSomething = true;
if (DeclType->isUnionType()) {
// Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field);
}
++Field;