//===--- 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.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "clang/Parse/Designator.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/DiagnosticSema.h"
using namespace clang;
/// Recursively replaces NULL values within the given initializer list
/// with expressions that perform value-initialization of the
/// appropriate type.
static void fillInValueInitializations(ASTContext &Context, InitListExpr *ILE) {
assert((ILE->getType() != Context.VoidTy) && "Should not have void type");
if (const RecordType *RType = ILE->getType()->getAsRecordType()) {
unsigned Init = 0, NumInits = ILE->getNumInits();
for (RecordDecl::field_iterator Field = RType->getDecl()->field_begin(),
FieldEnd = RType->getDecl()->field_end();
Field != FieldEnd; ++Field) {
if (Field->isUnnamedBitfield())
continue;
if (Init >= NumInits)
break;
// FIXME: Check for fields with reference type in C++?
if (!ILE->getInit(Init))
ILE->setInit(Init,
new (Context) CXXZeroInitValueExpr(Field->getType(),
SourceLocation(),
SourceLocation()));
else if (InitListExpr *InnerILE = dyn_cast<InitListExpr>(ILE->getInit(Init)))
fillInValueInitializations(Context, InnerILE);
++Init;
}
return;
}
QualType ElementType;
if (const ArrayType *AType = Context.getAsArrayType(ILE->getType()))
ElementType = AType->getElementType();
else if (const VectorType *VType = ILE->getType()->getAsVectorType())
ElementType = VType->getElementType();
else
ElementType = ILE->getType();
for (unsigned Init = 0, NumInits = ILE->getNumInits(); Init != NumInits;
++Init) {
if (!ILE->getInit(Init))
ILE->setInit(Init, new (Context) CXXZeroInitValueExpr(ElementType,
SourceLocation(),
SourceLocation()));
else if (InitListExpr *InnerILE = dyn_cast<InitListExpr>(ILE->getInit(Init)))
fillInValueInitializations(Context, InnerILE);
}
}
InitListChecker::InitListChecker(Sema *S, InitListExpr *IL, QualType &T) {
hadError = false;
SemaRef = S;
unsigned newIndex = 0;
unsigned newStructuredIndex = 0;
FullyStructuredList
= getStructuredSubobjectInit(IL, newIndex, T, 0, 0, SourceRange());
CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex);
if (!hadError) {
fillInValueInitializations(SemaRef->Context, FullyStructuredList);
}
}
int InitListChecker::numArrayElements(QualType DeclType) {
// FIXME: use a proper constant
int maxElements = 0x7FFFFFFF;
if (const ConstantArrayType *CAT =
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(),
FieldEnd = structDecl->field_end();
Field != FieldEnd; ++Field) {
if ((*Field)->getIdentifier() || !(*Field)->isBitField())
++InitializableMembers;
}
if (structDecl->isUnion())
return std::min(InitializableMembers, 1);
return InitializableMembers - structDecl->hasFlexibleArrayMember();
}
void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList,
QualType T, unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
int maxElements = 0;
if (T->isArrayType())
maxElements = numArrayElements(T);
else if (T->isStructureType() || T->isUnionType())