2008-05-02 06:18:59 +08:00
|
|
|
//===--- 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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2009-02-25 06:27:37 +08:00
|
|
|
// 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.
|
|
|
|
//
|
2009-02-25 06:48:58 +08:00
|
|
|
// This file also implements Sema::CheckInitializerTypes.
|
2008-05-02 06:18:59 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Sema.h"
|
2009-01-22 08:58:24 +08:00
|
|
|
#include "clang/Parse/Designator.h"
|
2008-05-02 06:18:59 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-05-28 00:10:08 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2009-02-25 07:10:27 +08:00
|
|
|
#include "clang/AST/ExprObjC.h"
|
2009-01-29 08:45:39 +08:00
|
|
|
#include <map>
|
2009-01-22 08:58:24 +08:00
|
|
|
using namespace clang;
|
2008-05-02 06:18:59 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Sema Initialization Checking
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-25 07:10:27 +08:00
|
|
|
static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
|
2009-02-27 07:26:43 +08:00
|
|
|
const ArrayType *AT = Context.getAsArrayType(DeclType);
|
|
|
|
if (!AT) return 0;
|
|
|
|
|
2009-05-30 02:22:49 +08:00
|
|
|
if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT))
|
|
|
|
return 0;
|
|
|
|
|
2009-02-27 07:26:43 +08:00
|
|
|
// See if this is a string literal or @encode.
|
|
|
|
Init = Init->IgnoreParens();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-27 07:26:43 +08:00
|
|
|
// 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);
|
2009-02-27 07:42:47 +08:00
|
|
|
if (SL == 0) return 0;
|
2009-05-31 18:54:53 +08:00
|
|
|
|
|
|
|
QualType ElemTy = Context.getCanonicalType(AT->getElementType());
|
2009-02-27 07:26:43 +08:00
|
|
|
// char array can be initialized with a narrow string.
|
|
|
|
// Only allow char x[] = "foo"; not char x[] = L"foo";
|
|
|
|
if (!SL->isWide())
|
2009-05-31 18:54:53 +08:00
|
|
|
return ElemTy->isCharType() ? Init : 0;
|
2009-02-27 07:26:43 +08:00
|
|
|
|
2009-05-31 18:54:53 +08:00
|
|
|
// wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with
|
|
|
|
// correction from DR343): "An array with element type compatible with a
|
|
|
|
// qualified or unqualified version of wchar_t may be initialized by a wide
|
|
|
|
// string literal, optionally enclosed in braces."
|
|
|
|
if (Context.typesAreCompatible(Context.getWCharType(),
|
|
|
|
ElemTy.getUnqualifiedType()))
|
2009-02-27 07:26:43 +08:00
|
|
|
return Init;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
|
2009-02-25 06:46:58 +08:00
|
|
|
bool DirectInit, Sema &S) {
|
2009-02-25 06:27:37 +08:00
|
|
|
// Get the type before calling CheckSingleAssignmentConstraints(), since
|
|
|
|
// it can promote the expression.
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType InitType = Init->getType();
|
|
|
|
|
2009-02-25 06:46:58 +08:00
|
|
|
if (S.getLangOptions().CPlusPlus) {
|
2009-02-25 06:27:37 +08:00
|
|
|
// FIXME: I dislike this error message. A lot.
|
2009-09-16 03:12:21 +08:00
|
|
|
if (S.PerformImplicitConversion(Init, DeclType,
|
|
|
|
"initializing", DirectInit)) {
|
|
|
|
ImplicitConversionSequence ICS;
|
|
|
|
OverloadCandidateSet CandidateSet;
|
|
|
|
if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined,
|
|
|
|
CandidateSet,
|
|
|
|
true, false, false) != S.OR_Ambiguous)
|
|
|
|
return S.Diag(Init->getSourceRange().getBegin(),
|
|
|
|
diag::err_typecheck_convert_incompatible)
|
|
|
|
<< DeclType << Init->getType() << "initializing"
|
|
|
|
<< Init->getSourceRange();
|
|
|
|
S.Diag(Init->getSourceRange().getBegin(),
|
|
|
|
diag::err_typecheck_convert_ambiguous)
|
|
|
|
<< DeclType << Init->getType() << Init->getSourceRange();
|
|
|
|
S.PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
|
|
|
|
return true;
|
|
|
|
}
|
2009-02-25 06:27:37 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:46:58 +08:00
|
|
|
Sema::AssignConvertType ConvTy =
|
|
|
|
S.CheckSingleAssignmentConstraints(DeclType, Init);
|
|
|
|
return S.DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
|
2009-02-25 06:27:37 +08:00
|
|
|
InitType, Init, "initializing");
|
|
|
|
}
|
|
|
|
|
2009-02-25 07:10:27 +08:00
|
|
|
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();
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 07:10:27 +08:00
|
|
|
const ArrayType *AT = S.Context.getAsArrayType(DeclT);
|
2009-02-25 06:27:37 +08:00
|
|
|
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// C99 6.7.8p14. We have an array of character type with unknown size
|
2009-02-25 06:27:37 +08:00
|
|
|
// being initialized to a string literal.
|
|
|
|
llvm::APSInt ConstVal(32);
|
2009-02-25 07:01:39 +08:00
|
|
|
ConstVal = StrLength;
|
2009-02-25 06:27:37 +08:00
|
|
|
// Return a new array type (C99 6.7.8p22).
|
2009-10-16 08:14:28 +08:00
|
|
|
DeclT = S.Context.getConstantArrayType(IAT->getElementType(),
|
|
|
|
ConstVal,
|
|
|
|
ArrayType::Normal, 0);
|
2009-02-25 07:01:39 +08:00
|
|
|
return;
|
2009-02-25 06:27:37 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 02:22:49 +08:00
|
|
|
const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 02:22:49 +08:00
|
|
|
// 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();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 02:22:49 +08:00
|
|
|
// 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);
|
2009-02-25 06:27:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
|
|
|
|
SourceLocation InitLoc,
|
2009-05-31 04:41:30 +08:00
|
|
|
DeclarationName InitEntity, bool DirectInit) {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (DeclType->isDependentType() ||
|
2009-11-20 02:03:26 +08:00
|
|
|
Init->isTypeDependent() || Init->isValueDependent()) {
|
|
|
|
// We have either a dependent type or a type- or value-dependent
|
|
|
|
// initializer, so we don't perform any additional checking at
|
|
|
|
// this point.
|
|
|
|
|
|
|
|
// If the declaration is a non-dependent, incomplete array type
|
|
|
|
// that has an initializer, then its type will be completed once
|
2009-11-20 07:25:22 +08:00
|
|
|
// the initializer is instantiated.
|
2009-11-20 02:03:26 +08:00
|
|
|
if (!DeclType->isDependentType()) {
|
|
|
|
if (const IncompleteArrayType *ArrayT
|
|
|
|
= Context.getAsIncompleteArrayType(DeclType)) {
|
2009-11-20 07:25:22 +08:00
|
|
|
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
|
|
|
|
if (!ILE->isTypeDependent()) {
|
|
|
|
// Compute the constant array type from the length of the
|
|
|
|
// initializer list.
|
|
|
|
// FIXME: This will be wrong if there are designated
|
|
|
|
// initializations. Good thing they don't exist in C++!
|
|
|
|
llvm::APInt NumElements(Context.getTypeSize(Context.getSizeType()),
|
|
|
|
ILE->getNumInits());
|
|
|
|
llvm::APInt Zero(Context.getTypeSize(Context.getSizeType()), 0);
|
|
|
|
if (NumElements == Zero) {
|
|
|
|
// Sizing an array implicitly to zero is not allowed by ISO C,
|
|
|
|
// but is supported by GNU.
|
|
|
|
Diag(ILE->getLocStart(), diag::ext_typecheck_zero_array_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
DeclType = Context.getConstantArrayType(ArrayT->getElementType(),
|
|
|
|
NumElements,
|
|
|
|
ArrayT->getSizeModifier(),
|
|
|
|
ArrayT->getIndexTypeCVRQualifiers());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make the array type-dependent by making it dependently-sized.
|
2009-11-20 02:03:26 +08:00
|
|
|
DeclType = Context.getDependentSizedArrayType(ArrayT->getElementType(),
|
|
|
|
/*NumElts=*/0,
|
|
|
|
ArrayT->getSizeModifier(),
|
|
|
|
ArrayT->getIndexTypeCVRQualifiers(),
|
|
|
|
SourceRange());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
return false;
|
2009-11-20 02:03:26 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
// C++ [dcl.init.ref]p1:
|
2009-03-17 07:22:08 +08:00
|
|
|
// A variable declared to be a T& or T&&, that is "reference to type T"
|
2009-02-25 06:27:37 +08:00
|
|
|
// (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())
|
2009-09-24 07:04:10 +08:00
|
|
|
return CheckReferenceInit(Init, DeclType, InitLoc,
|
2009-08-28 01:30:43 +08:00
|
|
|
/*SuppressUserConversions=*/false,
|
|
|
|
/*AllowExplicit=*/DirectInit,
|
|
|
|
/*ForceRValue=*/false);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
// 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();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
|
|
|
|
if (!InitList) {
|
|
|
|
// FIXME: Handle wide strings
|
2009-02-25 07:10:27 +08:00
|
|
|
if (Expr *Str = IsStringInit(Init, DeclType, Context)) {
|
|
|
|
CheckStringInit(Str, DeclType, *this);
|
2009-02-25 07:01:39 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
// 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());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
// -- 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.
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
if ((DeclTypeC.getLocalUnqualifiedType()
|
|
|
|
== InitTypeC.getLocalUnqualifiedType()) ||
|
2009-02-25 06:27:37 +08:00
|
|
|
IsDerivedFrom(InitTypeC, DeclTypeC)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
const CXXRecordDecl *RD =
|
2009-07-30 05:53:49 +08:00
|
|
|
cast<CXXRecordDecl>(DeclType->getAs<RecordType>()->getDecl());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-28 00:38:58 +08:00
|
|
|
// No need to make a CXXConstructExpr if both the ctor and dtor are
|
|
|
|
// trivial.
|
|
|
|
if (RD->hasTrivialConstructor() && RD->hasTrivialDestructor())
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-10 07:08:42 +08:00
|
|
|
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
CXXConstructorDecl *Constructor
|
2009-09-10 07:08:42 +08:00
|
|
|
= PerformInitializationByConstructor(DeclType,
|
|
|
|
MultiExprArg(*this,
|
|
|
|
(void **)&Init, 1),
|
|
|
|
InitLoc, Init->getSourceRange(),
|
|
|
|
InitEntity,
|
|
|
|
DirectInit? IK_Direct : IK_Copy,
|
|
|
|
ConstructorArgs);
|
2009-05-28 00:10:08 +08:00
|
|
|
if (!Constructor)
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
OwningExprResult InitResult =
|
2009-09-05 15:40:38 +08:00
|
|
|
BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclType, Constructor,
|
2009-09-10 07:08:42 +08:00
|
|
|
move_arg(ConstructorArgs));
|
2009-08-25 13:12:04 +08:00
|
|
|
if (InitResult.isInvalid())
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-25 13:12:04 +08:00
|
|
|
Init = InitResult.takeAs<Expr>();
|
2009-05-28 00:10:08 +08:00
|
|
|
return false;
|
2009-02-25 06:27:37 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
// -- 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.
|
2009-05-16 15:39:55 +08:00
|
|
|
// FIXME: We're pretending to do copy elision here; return to this when we
|
|
|
|
// have ASTs for such things.
|
2009-02-25 06:27:37 +08:00
|
|
|
if (!PerformImplicitConversion(Init, DeclType, "initializing"))
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
if (InitEntity)
|
|
|
|
return Diag(InitLoc, diag::err_cannot_initialize_decl)
|
2009-06-26 12:45:06 +08:00
|
|
|
<< InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
|
|
|
|
<< Init->getType() << Init->getSourceRange();
|
|
|
|
return Diag(InitLoc, diag::err_cannot_initialize_decl_noname)
|
2009-02-25 06:27:37 +08:00
|
|
|
<< DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
|
|
|
|
<< Init->getType() << Init->getSourceRange();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
// C99 6.7.8p16.
|
|
|
|
if (DeclType->isArrayType())
|
|
|
|
return Diag(Init->getLocStart(), diag::err_array_init_list_required)
|
2009-06-26 12:45:06 +08:00
|
|
|
<< Init->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-25 06:46:58 +08:00
|
|
|
return CheckSingleInitializer(Init, DeclType, DirectInit, *this);
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
|
|
|
|
2009-02-25 06:27:37 +08:00
|
|
|
bool hadError = CheckInitList(InitList, DeclType);
|
|
|
|
Init = InitList;
|
|
|
|
return hadError;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Semantic checking for initializer lists.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-01-29 09:05:33 +08:00
|
|
|
/// @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.
|
2009-02-25 06:48:58 +08:00
|
|
|
namespace {
|
2009-01-29 08:45:39 +08:00
|
|
|
class InitListChecker {
|
2009-02-25 06:50:46 +08:00
|
|
|
Sema &SemaRef;
|
2009-01-29 08:45:39 +08:00
|
|
|
bool hadError;
|
|
|
|
std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
|
|
|
|
InitListExpr *FullyStructuredList;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
void CheckImplicitInitList(InitListExpr *ParentIList, QualType T,
|
2009-01-29 09:05:33 +08:00
|
|
|
unsigned &Index, InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject = false);
|
2009-01-29 08:45:39 +08:00
|
|
|
void CheckExplicitInitList(InitListExpr *IList, QualType &T,
|
2009-01-29 09:05:33 +08:00
|
|
|
unsigned &Index, InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject = false);
|
2009-09-09 23:08:12 +08:00
|
|
|
void CheckListElementTypes(InitListExpr *IList, QualType &DeclType,
|
|
|
|
bool SubobjectIsDesignatorContext,
|
2009-01-29 08:45:39 +08:00
|
|
|
unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject = false);
|
2009-09-09 23:08:12 +08:00
|
|
|
void CheckSubElementType(InitListExpr *IList, QualType ElemType,
|
2009-01-29 08:45:39 +08:00
|
|
|
unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2009-09-09 23:08:12 +08:00
|
|
|
void CheckScalarType(InitListExpr *IList, QualType DeclType,
|
2009-01-29 08:45:39 +08:00
|
|
|
unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2009-09-09 23:08:12 +08:00
|
|
|
void CheckReferenceType(InitListExpr *IList, QualType DeclType,
|
2009-01-31 06:09:00 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2009-01-29 08:45:39 +08:00
|
|
|
void CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2009-09-09 23:08:12 +08:00
|
|
|
void CheckStructUnionTypes(InitListExpr *IList, QualType DeclType,
|
|
|
|
RecordDecl::field_iterator Field,
|
2009-01-29 08:45:39 +08:00
|
|
|
bool SubobjectIsDesignatorContext, unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject = false);
|
2009-09-09 23:08:12 +08:00
|
|
|
void CheckArrayType(InitListExpr *IList, QualType &DeclType,
|
|
|
|
llvm::APSInt elementIndex,
|
2009-01-29 08:45:39 +08:00
|
|
|
bool SubobjectIsDesignatorContext, unsigned &Index,
|
2009-01-29 09:05:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex);
|
2009-09-09 23:08:12 +08:00
|
|
|
bool CheckDesignatedInitializer(InitListExpr *IList, DesignatedInitExpr *DIE,
|
2009-04-15 12:56:10 +08:00
|
|
|
unsigned DesigIdx,
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType &CurrentObjectType,
|
2009-01-29 08:45:39 +08:00
|
|
|
RecordDecl::field_iterator *NextField,
|
|
|
|
llvm::APSInt *NextElementIndex,
|
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
bool FinishSubobjectInit,
|
|
|
|
bool TopLevelObject);
|
2009-01-29 08:45:39 +08:00
|
|
|
InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
|
|
|
|
QualType CurrentObjectType,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned StructuredIndex,
|
|
|
|
SourceRange InitRange);
|
2009-01-29 09:05:33 +08:00
|
|
|
void UpdateStructuredListElement(InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex,
|
2009-01-29 08:45:39 +08:00
|
|
|
Expr *expr);
|
|
|
|
int numArrayElements(QualType DeclType);
|
|
|
|
int numStructUnionElements(QualType DeclType);
|
2009-01-31 06:09:00 +08:00
|
|
|
|
|
|
|
void FillInValueInitializations(InitListExpr *ILE);
|
2009-01-29 08:45:39 +08:00
|
|
|
public:
|
2009-02-25 06:50:46 +08:00
|
|
|
InitListChecker(Sema &S, InitListExpr *IL, QualType &T);
|
2009-01-29 08:45:39 +08:00
|
|
|
bool HadError() { return hadError; }
|
|
|
|
|
|
|
|
// @brief Retrieves the fully-structured initializer list used for
|
|
|
|
// semantic analysis and code generation.
|
|
|
|
InitListExpr *getFullyStructuredList() const { return FullyStructuredList; }
|
|
|
|
};
|
2009-02-25 06:48:58 +08:00
|
|
|
} // end anonymous namespace
|
2009-01-29 13:10:57 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
/// Recursively replaces NULL values within the given initializer list
|
|
|
|
/// with expressions that perform value-initialization of the
|
|
|
|
/// appropriate type.
|
2009-01-31 06:09:00 +08:00
|
|
|
void InitListChecker::FillInValueInitializations(InitListExpr *ILE) {
|
2009-09-09 23:08:12 +08:00
|
|
|
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
|
2009-01-31 06:09:00 +08:00
|
|
|
"Should not have void type");
|
2009-02-03 01:43:21 +08:00
|
|
|
SourceLocation Loc = ILE->getSourceRange().getBegin();
|
|
|
|
if (ILE->getSyntacticForm())
|
|
|
|
Loc = ILE->getSyntacticForm()->getSourceRange().getBegin();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned Init = 0, NumInits = ILE->getNumInits();
|
2009-09-09 23:08:12 +08:00
|
|
|
for (RecordDecl::field_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
Field = RType->getDecl()->field_begin(),
|
|
|
|
FieldEnd = RType->getDecl()->field_end();
|
2009-01-29 05:54:33 +08:00
|
|
|
Field != FieldEnd; ++Field) {
|
|
|
|
if (Field->isUnnamedBitfield())
|
|
|
|
continue;
|
|
|
|
|
2009-02-03 01:43:21 +08:00
|
|
|
if (Init >= NumInits || !ILE->getInit(Init)) {
|
2009-01-31 06:09:00 +08:00
|
|
|
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
|
2009-09-09 23:08:12 +08:00
|
|
|
// ill-formed.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized)
|
2009-01-31 06:09:00 +08:00
|
|
|
<< Field->getType()
|
|
|
|
<< ILE->getSyntacticForm()->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(Field->getLocation(),
|
2009-01-31 06:09:00 +08:00
|
|
|
diag::note_uninit_reference_member);
|
|
|
|
hadError = true;
|
2009-02-03 01:43:21 +08:00
|
|
|
return;
|
2009-02-25 06:50:46 +08:00
|
|
|
} else if (SemaRef.CheckValueInitialization(Field->getType(), Loc)) {
|
2009-02-03 01:43:21 +08:00
|
|
|
hadError = true;
|
|
|
|
return;
|
2009-01-31 06:09:00 +08:00
|
|
|
}
|
2009-02-03 01:43:21 +08:00
|
|
|
|
2009-05-16 15:39:55 +08:00
|
|
|
// 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)?
|
2009-02-03 01:43:21 +08:00
|
|
|
if (Init < NumInits && !hadError)
|
2009-09-09 23:08:12 +08:00
|
|
|
ILE->setInit(Init,
|
2009-02-25 06:50:46 +08:00
|
|
|
new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()));
|
2009-09-09 23:08:12 +08:00
|
|
|
} else if (InitListExpr *InnerILE
|
2009-01-30 01:44:32 +08:00
|
|
|
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
|
2009-01-31 06:09:00 +08:00
|
|
|
FillInValueInitializations(InnerILE);
|
2009-01-29 05:54:33 +08:00
|
|
|
++Init;
|
2009-01-31 06:09:00 +08:00
|
|
|
|
|
|
|
// Only look at the first initialization of a union.
|
|
|
|
if (RType->getDecl()->isUnion())
|
|
|
|
break;
|
2009-01-29 05:54:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
|
|
|
|
QualType ElementType;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-03 01:43:21 +08:00
|
|
|
unsigned NumInits = ILE->getNumInits();
|
|
|
|
unsigned NumElements = NumInits;
|
2009-02-25 06:50:46 +08:00
|
|
|
if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) {
|
2009-01-29 05:54:33 +08:00
|
|
|
ElementType = AType->getElementType();
|
2009-02-03 01:43:21 +08:00
|
|
|
if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
|
|
|
|
NumElements = CAType->getSize().getZExtValue();
|
2009-09-22 07:43:11 +08:00
|
|
|
} else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
|
2009-01-29 05:54:33 +08:00
|
|
|
ElementType = VType->getElementType();
|
2009-02-03 01:43:21 +08:00
|
|
|
NumElements = VType->getNumElements();
|
2009-09-09 23:08:12 +08:00
|
|
|
} else
|
2009-01-29 05:54:33 +08:00
|
|
|
ElementType = ILE->getType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-02-03 01:43:21 +08:00
|
|
|
for (unsigned Init = 0; Init != NumElements; ++Init) {
|
|
|
|
if (Init >= NumInits || !ILE->getInit(Init)) {
|
2009-02-25 06:50:46 +08:00
|
|
|
if (SemaRef.CheckValueInitialization(ElementType, Loc)) {
|
2009-02-03 01:43:21 +08:00
|
|
|
hadError = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-05-16 15:39:55 +08:00
|
|
|
// 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)?
|
2009-02-03 01:43:21 +08:00
|
|
|
if (Init < NumInits && !hadError)
|
2009-09-09 23:08:12 +08:00
|
|
|
ILE->setInit(Init,
|
2009-02-25 06:50:46 +08:00
|
|
|
new (SemaRef.Context) ImplicitValueInitExpr(ElementType));
|
2009-08-05 05:02:39 +08:00
|
|
|
} else if (InitListExpr *InnerILE
|
|
|
|
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
|
2009-01-31 06:09:00 +08:00
|
|
|
FillInValueInitializations(InnerILE);
|
2009-01-29 05:54:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-29 13:10:57 +08:00
|
|
|
|
2009-02-25 06:50:46 +08:00
|
|
|
InitListChecker::InitListChecker(Sema &S, InitListExpr *IL, QualType &T)
|
|
|
|
: SemaRef(S) {
|
2008-05-02 06:18:59 +08:00
|
|
|
hadError = false;
|
2008-05-20 04:00:43 +08:00
|
|
|
|
2008-05-20 03:16:24 +08:00
|
|
|
unsigned newIndex = 0;
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned newStructuredIndex = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
FullyStructuredList
|
2009-03-02 01:12:46 +08:00
|
|
|
= getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
|
2009-02-05 06:46:25 +08:00
|
|
|
CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex,
|
|
|
|
/*TopLevelObject=*/true);
|
2008-05-20 04:00:43 +08:00
|
|
|
|
2009-01-31 06:09:00 +08:00
|
|
|
if (!hadError)
|
|
|
|
FillInValueInitializations(FullyStructuredList);
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int InitListChecker::numArrayElements(QualType DeclType) {
|
2008-05-25 21:22:35 +08:00
|
|
|
// FIXME: use a proper constant
|
|
|
|
int maxElements = 0x7FFFFFFF;
|
2008-08-04 15:31:14 +08:00
|
|
|
if (const ConstantArrayType *CAT =
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Context.getAsConstantArrayType(DeclType)) {
|
2008-05-02 06:18:59 +08:00
|
|
|
maxElements = static_cast<int>(CAT->getSize().getZExtValue());
|
|
|
|
}
|
|
|
|
return maxElements;
|
|
|
|
}
|
|
|
|
|
|
|
|
int InitListChecker::numStructUnionElements(QualType DeclType) {
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl();
|
2009-01-29 05:54:33 +08:00
|
|
|
int InitializableMembers = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
for (RecordDecl::field_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
Field = structDecl->field_begin(),
|
|
|
|
FieldEnd = structDecl->field_end();
|
2009-01-29 05:54:33 +08:00
|
|
|
Field != FieldEnd; ++Field) {
|
|
|
|
if ((*Field)->getIdentifier() || !(*Field)->isBitField())
|
|
|
|
++InitializableMembers;
|
|
|
|
}
|
2008-06-10 07:19:58 +08:00
|
|
|
if (structDecl->isUnion())
|
2008-05-25 22:03:31 +08:00
|
|
|
return std::min(InitializableMembers, 1);
|
|
|
|
return InitializableMembers - structDecl->hasFlexibleArrayMember();
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList,
|
2009-01-29 05:54:33 +08:00
|
|
|
QualType T, unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject) {
|
2008-05-02 06:18:59 +08:00
|
|
|
int maxElements = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-02 06:18:59 +08:00
|
|
|
if (T->isArrayType())
|
|
|
|
maxElements = numArrayElements(T);
|
|
|
|
else if (T->isStructureType() || T->isUnionType())
|
|
|
|
maxElements = numStructUnionElements(T);
|
2008-05-20 03:16:24 +08:00
|
|
|
else if (T->isVectorType())
|
2009-09-22 07:43:11 +08:00
|
|
|
maxElements = T->getAs<VectorType>()->getNumElements();
|
2008-05-02 06:18:59 +08:00
|
|
|
else
|
|
|
|
assert(0 && "CheckImplicitInitList(): Illegal type");
|
2008-05-20 03:16:24 +08:00
|
|
|
|
2008-05-25 21:49:22 +08:00
|
|
|
if (maxElements == 0) {
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
|
2008-05-25 21:49:22 +08:00
|
|
|
diag::err_implicit_empty_initializer);
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
2008-05-25 21:49:22 +08:00
|
|
|
hadError = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Build a structured initializer list corresponding to this subobject.
|
|
|
|
InitListExpr *StructuredSubobjectInitList
|
2009-09-09 23:08:12 +08:00
|
|
|
= getStructuredSubobjectInit(ParentIList, Index, T, StructuredList,
|
|
|
|
StructuredIndex,
|
2009-03-02 01:12:46 +08:00
|
|
|
SourceRange(ParentIList->getInit(Index)->getSourceRange().getBegin(),
|
|
|
|
ParentIList->getSourceRange().getEnd()));
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned StructuredSubobjectInitIndex = 0;
|
|
|
|
|
|
|
|
// Check the element types and build the structural subobject.
|
2009-02-03 01:43:21 +08:00
|
|
|
unsigned StartIndex = Index;
|
2009-01-29 05:54:33 +08:00
|
|
|
CheckListElementTypes(ParentIList, T, false, Index,
|
2009-09-09 23:08:12 +08:00
|
|
|
StructuredSubobjectInitList,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredSubobjectInitIndex,
|
|
|
|
TopLevelObject);
|
2009-02-03 01:43:21 +08:00
|
|
|
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
|
2009-03-20 08:32:56 +08:00
|
|
|
StructuredSubobjectInitList->setType(T);
|
|
|
|
|
2009-03-02 01:12:46 +08:00
|
|
|
// Update the structured sub-object initializer so that it's ending
|
2009-02-03 01:43:21 +08:00
|
|
|
// range corresponds with the end of the last initializer it used.
|
|
|
|
if (EndIndex < ParentIList->getNumInits()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceLocation EndLoc
|
2009-02-03 01:43:21 +08:00
|
|
|
= ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
|
|
|
|
StructuredSubobjectInitList->setRBraceLoc(EndLoc);
|
|
|
|
}
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2008-05-06 08:23:44 +08:00
|
|
|
void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject) {
|
2008-05-20 04:00:43 +08:00
|
|
|
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
|
2009-01-29 05:54:33 +08:00
|
|
|
SyntacticToSemantic[IList] = StructuredList;
|
|
|
|
StructuredList->setSyntacticForm(IList);
|
2009-09-09 23:08:12 +08:00
|
|
|
CheckListElementTypes(IList, T, true, Index, StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredIndex, TopLevelObject);
|
2008-05-06 08:23:44 +08:00
|
|
|
IList->setType(T);
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList->setType(T);
|
2008-05-25 21:22:35 +08:00
|
|
|
if (hadError)
|
|
|
|
return;
|
2008-05-20 04:00:43 +08:00
|
|
|
|
2008-05-25 21:22:35 +08:00
|
|
|
if (Index < IList->getNumInits()) {
|
2008-05-20 04:00:43 +08:00
|
|
|
// We have leftover initializers
|
2009-05-30 04:20:05 +08:00
|
|
|
if (StructuredIndex == 1 &&
|
|
|
|
IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) {
|
2009-02-19 06:23:55 +08:00
|
|
|
unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
|
2009-05-30 04:20:05 +08:00
|
|
|
if (SemaRef.getLangOptions().CPlusPlus) {
|
2009-02-19 06:23:55 +08:00
|
|
|
DK = diag::err_excess_initializers_in_char_array_initializer;
|
2009-05-30 04:20:05 +08:00
|
|
|
hadError = true;
|
|
|
|
}
|
2008-05-20 04:12:18 +08:00
|
|
|
// Special-case
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
|
2008-11-19 13:27:50 +08:00
|
|
|
<< IList->getInit(Index)->getSourceRange();
|
2008-05-20 13:25:56 +08:00
|
|
|
} else if (!T->isIncompleteType()) {
|
2009-01-31 06:26:29 +08:00
|
|
|
// Don't complain for incomplete types, since we'll get an error
|
|
|
|
// elsewhere
|
2009-02-05 06:46:25 +08:00
|
|
|
QualType CurrentObjectType = StructuredList->getType();
|
2009-09-09 23:08:12 +08:00
|
|
|
int initKind =
|
2009-02-05 06:46:25 +08:00
|
|
|
CurrentObjectType->isArrayType()? 0 :
|
|
|
|
CurrentObjectType->isVectorType()? 1 :
|
|
|
|
CurrentObjectType->isScalarType()? 2 :
|
|
|
|
CurrentObjectType->isUnionType()? 3 :
|
|
|
|
4;
|
2009-02-19 06:23:55 +08:00
|
|
|
|
|
|
|
unsigned DK = diag::warn_excess_initializers;
|
2009-05-30 04:20:05 +08:00
|
|
|
if (SemaRef.getLangOptions().CPlusPlus) {
|
|
|
|
DK = diag::err_excess_initializers;
|
2009-07-08 05:53:06 +08:00
|
|
|
hadError = true;
|
|
|
|
}
|
|
|
|
if (SemaRef.getLangOptions().OpenCL && initKind == 1) {
|
|
|
|
DK = diag::err_excess_initializers;
|
2009-05-30 04:20:05 +08:00
|
|
|
hadError = true;
|
|
|
|
}
|
2009-02-19 06:23:55 +08:00
|
|
|
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK)
|
2009-02-05 06:46:25 +08:00
|
|
|
<< initKind << IList->getInit(Index)->getSourceRange();
|
2008-05-20 04:00:43 +08:00
|
|
|
}
|
|
|
|
}
|
2008-05-20 04:20:43 +08:00
|
|
|
|
2009-05-16 19:45:48 +08:00
|
|
|
if (T->isScalarType() && !TopLevelObject)
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
|
2009-04-02 07:51:29 +08:00
|
|
|
<< IList->getSourceRange()
|
|
|
|
<< CodeModificationHint::CreateRemoval(SourceRange(IList->getLocStart()))
|
|
|
|
<< CodeModificationHint::CreateRemoval(SourceRange(IList->getLocEnd()));
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2008-05-20 03:16:24 +08:00
|
|
|
void InitListChecker::CheckListElementTypes(InitListExpr *IList,
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType &DeclType,
|
2009-01-23 07:26:18 +08:00
|
|
|
bool SubobjectIsDesignatorContext,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject) {
|
2008-05-20 04:00:43 +08:00
|
|
|
if (DeclType->isScalarType()) {
|
2009-01-29 08:39:20 +08:00
|
|
|
CheckScalarType(IList, DeclType, Index, StructuredList, StructuredIndex);
|
2008-05-20 04:00:43 +08:00
|
|
|
} else if (DeclType->isVectorType()) {
|
2009-01-29 05:54:33 +08:00
|
|
|
CheckVectorType(IList, DeclType, Index, StructuredList, StructuredIndex);
|
2009-01-31 01:31:00 +08:00
|
|
|
} else if (DeclType->isAggregateType()) {
|
|
|
|
if (DeclType->isRecordType()) {
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
CheckStructUnionTypes(IList, DeclType, RD->field_begin(),
|
2009-01-29 05:54:33 +08:00
|
|
|
SubobjectIsDesignatorContext, Index,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredList, StructuredIndex,
|
|
|
|
TopLevelObject);
|
2009-01-23 07:26:18 +08:00
|
|
|
} else if (DeclType->isArrayType()) {
|
2009-01-24 00:54:12 +08:00
|
|
|
llvm::APSInt Zero(
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
|
2009-01-24 00:54:12 +08:00
|
|
|
false);
|
2009-01-29 05:54:33 +08:00
|
|
|
CheckArrayType(IList, DeclType, Zero, SubobjectIsDesignatorContext, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
2009-08-05 05:02:39 +08:00
|
|
|
} else
|
2009-01-29 05:54:33 +08:00
|
|
|
assert(0 && "Aggregate that isn't a structure or array?!");
|
2008-08-11 00:05:48 +08:00
|
|
|
} else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
|
|
|
|
// This type is invalid, issue a diagnostic.
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< DeclType;
|
2008-05-20 13:25:56 +08:00
|
|
|
hadError = true;
|
2009-01-31 06:09:00 +08:00
|
|
|
} 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.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
|
2009-01-31 06:09:00 +08:00
|
|
|
<< DeclType << IList->getSourceRange();
|
|
|
|
hadError = true;
|
|
|
|
} else if (DeclType->isReferenceType()) {
|
|
|
|
CheckReferenceType(IList, DeclType, Index, StructuredList, StructuredIndex);
|
2008-05-02 06:18:59 +08:00
|
|
|
} else {
|
|
|
|
// In C, all types are either scalars or aggregates, but
|
2009-09-09 23:08:12 +08:00
|
|
|
// additional handling is needed here for C++ (and possibly others?).
|
2008-05-02 06:18:59 +08:00
|
|
|
assert(0 && "Unsupported initializer type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-20 03:16:24 +08:00
|
|
|
void InitListChecker::CheckSubElementType(InitListExpr *IList,
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType ElemType,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2009-01-29 08:39:20 +08:00
|
|
|
Expr *expr = IList->getInit(Index);
|
2008-05-20 04:00:43 +08:00
|
|
|
if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
|
|
|
|
unsigned newIndex = 0;
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned newStructuredIndex = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
InitListExpr *newStructuredList
|
2009-01-29 05:54:33 +08:00
|
|
|
= getStructuredSubobjectInit(IList, Index, ElemType,
|
|
|
|
StructuredList, StructuredIndex,
|
|
|
|
SubInitList->getSourceRange());
|
2009-09-09 23:08:12 +08:00
|
|
|
CheckExplicitInitList(SubInitList, ElemType, newIndex,
|
2009-01-29 05:54:33 +08:00
|
|
|
newStructuredList, newStructuredIndex);
|
|
|
|
++StructuredIndex;
|
|
|
|
++Index;
|
2009-02-25 07:10:27 +08:00
|
|
|
} else if (Expr *Str = IsStringInit(expr, ElemType, SemaRef.Context)) {
|
|
|
|
CheckStringInit(Str, ElemType, SemaRef);
|
2009-02-25 06:41:04 +08:00
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
2008-05-20 04:00:43 +08:00
|
|
|
} else if (ElemType->isScalarType()) {
|
2009-01-29 08:39:20 +08:00
|
|
|
CheckScalarType(IList, ElemType, Index, StructuredList, StructuredIndex);
|
2009-01-31 06:09:00 +08:00
|
|
|
} else if (ElemType->isReferenceType()) {
|
|
|
|
CheckReferenceType(IList, ElemType, Index, StructuredList, StructuredIndex);
|
2008-05-20 03:16:24 +08:00
|
|
|
} else {
|
2009-02-25 06:50:46 +08:00
|
|
|
if (SemaRef.getLangOptions().CPlusPlus) {
|
2009-01-31 06:09:00 +08:00
|
|
|
// 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. [...]
|
2009-09-09 23:08:12 +08:00
|
|
|
ImplicitConversionSequence ICS
|
2009-08-28 01:18:13 +08:00
|
|
|
= SemaRef.TryCopyInitialization(expr, ElemType,
|
|
|
|
/*SuppressUserConversions=*/false,
|
2009-08-28 01:37:39 +08:00
|
|
|
/*ForceRValue=*/false,
|
|
|
|
/*InOverloadResolution=*/false);
|
2009-08-28 01:18:13 +08:00
|
|
|
|
2009-01-31 06:09:00 +08:00
|
|
|
if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion) {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS,
|
2009-01-31 06:09:00 +08:00
|
|
|
"initializing"))
|
|
|
|
hadError = true;
|
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
|
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through for subaggregate initialization
|
|
|
|
} else {
|
2009-09-09 23:08:12 +08:00
|
|
|
// C99 6.7.8p13:
|
2009-01-31 06:09:00 +08:00
|
|
|
//
|
|
|
|
// 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.
|
2009-06-13 18:38:46 +08:00
|
|
|
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
|
2009-05-30 02:22:49 +08:00
|
|
|
SemaRef.Context.hasSameUnqualifiedType(expr->getType(), ElemType)) {
|
2009-01-31 06:09:00 +08:00
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
|
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through for subaggregate initialization
|
|
|
|
}
|
|
|
|
|
|
|
|
// C++ [dcl.init.aggr]p12:
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2009-01-31 06:09:00 +08:00
|
|
|
// [...] 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()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
CheckImplicitInitList(IList, ElemType, Index, StructuredList,
|
2009-01-31 06:09:00 +08:00
|
|
|
StructuredIndex);
|
|
|
|
++StructuredIndex;
|
|
|
|
} else {
|
|
|
|
// We cannot initialize this element, so let
|
|
|
|
// PerformCopyInitialization produce the appropriate diagnostic.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.PerformCopyInitialization(expr, ElemType, "initializing");
|
2009-01-31 06:09:00 +08:00
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
|
|
|
}
|
|
|
|
}
|
2008-05-20 03:16:24 +08:00
|
|
|
}
|
|
|
|
|
2009-01-31 06:09:00 +08:00
|
|
|
void InitListChecker::CheckScalarType(InitListExpr *IList, QualType DeclType,
|
2009-01-29 08:39:20 +08:00
|
|
|
unsigned &Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2008-05-02 06:18:59 +08:00
|
|
|
if (Index < IList->getNumInits()) {
|
2009-01-29 08:39:20 +08:00
|
|
|
Expr *expr = IList->getInit(Index);
|
2008-05-20 04:00:43 +08:00
|
|
|
if (isa<InitListExpr>(expr)) {
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(),
|
2008-11-19 13:27:50 +08:00
|
|
|
diag::err_many_braces_around_scalar_init)
|
|
|
|
<< IList->getSourceRange();
|
2008-05-20 04:12:18 +08:00
|
|
|
hadError = true;
|
|
|
|
++Index;
|
2009-01-29 05:54:33 +08:00
|
|
|
++StructuredIndex;
|
2008-05-20 04:12:18 +08:00
|
|
|
return;
|
2009-01-22 08:58:24 +08:00
|
|
|
} else if (isa<DesignatedInitExpr>(expr)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(expr->getSourceRange().getBegin(),
|
2009-01-22 08:58:24 +08:00
|
|
|
diag::err_designator_for_scalar_init)
|
|
|
|
<< DeclType << expr->getSourceRange();
|
|
|
|
hadError = true;
|
|
|
|
++Index;
|
2009-01-29 05:54:33 +08:00
|
|
|
++StructuredIndex;
|
2009-01-22 08:58:24 +08:00
|
|
|
return;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2008-05-20 04:00:43 +08:00
|
|
|
Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
|
2009-02-25 06:50:46 +08:00
|
|
|
if (CheckSingleInitializer(expr, DeclType, false, SemaRef))
|
2008-05-20 04:12:18 +08:00
|
|
|
hadError = true; // types weren't compatible.
|
2009-01-22 08:58:24 +08:00
|
|
|
else if (savExpr != expr) {
|
2008-05-20 04:00:43 +08:00
|
|
|
// The type was promoted, update initializer list.
|
2009-01-29 08:39:20 +08:00
|
|
|
IList->setInit(Index, expr);
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
if (hadError)
|
|
|
|
++StructuredIndex;
|
|
|
|
else
|
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
|
2008-05-02 06:18:59 +08:00
|
|
|
++Index;
|
2008-05-20 04:12:18 +08:00
|
|
|
} else {
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
|
2008-11-19 13:27:50 +08:00
|
|
|
<< IList->getSourceRange();
|
2008-05-20 04:12:18 +08:00
|
|
|
hadError = true;
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
2008-05-20 04:12:18 +08:00
|
|
|
return;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-31 06:09:00 +08:00
|
|
|
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)) {
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
|
2009-01-31 06:09:00 +08:00
|
|
|
<< DeclType << IList->getSourceRange();
|
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-01-31 06:09:00 +08:00
|
|
|
|
|
|
|
Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer.
|
2009-08-28 01:30:43 +08:00
|
|
|
if (SemaRef.CheckReferenceInit(expr, DeclType,
|
2009-09-24 07:04:10 +08:00
|
|
|
/*FIXME:*/expr->getLocStart(),
|
2009-08-28 01:30:43 +08:00
|
|
|
/*SuppressUserConversions=*/false,
|
|
|
|
/*AllowExplicit=*/false,
|
2009-09-09 23:08:12 +08:00
|
|
|
/*ForceRValue=*/false))
|
2009-01-31 06:09:00 +08:00
|
|
|
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 {
|
2009-05-16 15:39:55 +08:00
|
|
|
// 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.
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(),
|
2009-01-31 06:09:00 +08:00
|
|
|
diag::err_init_reference_member_uninitialized)
|
|
|
|
<< DeclType
|
|
|
|
<< IList->getSourceRange();
|
|
|
|
hadError = true;
|
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2008-05-02 06:18:59 +08:00
|
|
|
if (Index < IList->getNumInits()) {
|
2009-09-22 07:43:11 +08:00
|
|
|
const VectorType *VT = DeclType->getAs<VectorType>();
|
2009-08-11 07:49:36 +08:00
|
|
|
unsigned maxElements = VT->getNumElements();
|
|
|
|
unsigned numEltsInit = 0;
|
2008-05-02 06:18:59 +08:00
|
|
|
QualType elementType = VT->getElementType();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-11 07:49:36 +08:00
|
|
|
if (!SemaRef.getLangOptions().OpenCL) {
|
|
|
|
for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) {
|
|
|
|
// Don't attempt to go past the end of the init list
|
|
|
|
if (Index >= IList->getNumInits())
|
|
|
|
break;
|
|
|
|
CheckSubElementType(IList, elementType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// OpenCL initializers allows vectors to be constructed from vectors.
|
|
|
|
for (unsigned i = 0; i < maxElements; ++i) {
|
|
|
|
// Don't attempt to go past the end of the init list
|
|
|
|
if (Index >= IList->getNumInits())
|
|
|
|
break;
|
|
|
|
QualType IType = IList->getInit(Index)->getType();
|
|
|
|
if (!IType->isVectorType()) {
|
|
|
|
CheckSubElementType(IList, elementType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
++numEltsInit;
|
|
|
|
} else {
|
2009-09-22 07:43:11 +08:00
|
|
|
const VectorType *IVT = IType->getAs<VectorType>();
|
2009-08-11 07:49:36 +08:00
|
|
|
unsigned numIElts = IVT->getNumElements();
|
|
|
|
QualType VecType = SemaRef.Context.getExtVectorType(elementType,
|
|
|
|
numIElts);
|
|
|
|
CheckSubElementType(IList, VecType, Index,
|
|
|
|
StructuredList, StructuredIndex);
|
|
|
|
numEltsInit += numIElts;
|
|
|
|
}
|
|
|
|
}
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-11 07:49:36 +08:00
|
|
|
// OpenCL & AltiVec require all elements to be initialized.
|
|
|
|
if (numEltsInit != maxElements)
|
|
|
|
if (SemaRef.getLangOptions().OpenCL || SemaRef.getLangOptions().AltiVec)
|
|
|
|
SemaRef.Diag(IList->getSourceRange().getBegin(),
|
|
|
|
diag::err_vector_incorrect_num_initializers)
|
|
|
|
<< (numEltsInit < maxElements) << maxElements << numEltsInit;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
|
2009-01-23 07:26:18 +08:00
|
|
|
llvm::APSInt elementIndex,
|
2009-09-09 23:08:12 +08:00
|
|
|
bool SubobjectIsDesignatorContext,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex) {
|
2008-05-02 06:18:59 +08:00
|
|
|
// Check for the special-case of initializing an array with a string.
|
|
|
|
if (Index < IList->getNumInits()) {
|
2009-02-25 07:10:27 +08:00
|
|
|
if (Expr *Str = IsStringInit(IList->getInit(Index), DeclType,
|
|
|
|
SemaRef.Context)) {
|
|
|
|
CheckStringInit(Str, DeclType, SemaRef);
|
2009-01-29 05:54:33 +08:00
|
|
|
// 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.
|
2009-02-25 06:41:04 +08:00
|
|
|
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
|
2009-02-25 06:50:46 +08:00
|
|
|
StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
|
2008-05-02 06:18:59 +08:00
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2008-08-04 15:31:14 +08:00
|
|
|
if (const VariableArrayType *VAT =
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Context.getAsVariableArrayType(DeclType)) {
|
2008-05-25 21:22:35 +08:00
|
|
|
// 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).
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
|
2008-11-19 13:27:50 +08:00
|
|
|
diag::err_variable_object_no_init)
|
|
|
|
<< VAT->getSizeExpr()->getSourceRange();
|
2008-05-25 21:22:35 +08:00
|
|
|
hadError = true;
|
2009-01-29 05:54:33 +08:00
|
|
|
++Index;
|
|
|
|
++StructuredIndex;
|
2008-05-25 21:22:35 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
// We might know the maximum number of elements in advance.
|
2009-01-29 05:54:33 +08:00
|
|
|
llvm::APSInt maxElements(elementIndex.getBitWidth(),
|
|
|
|
elementIndex.isUnsigned());
|
2009-01-22 08:58:24 +08:00
|
|
|
bool maxElementsKnown = false;
|
|
|
|
if (const ConstantArrayType *CAT =
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Context.getAsConstantArrayType(DeclType)) {
|
2009-01-22 08:58:24 +08:00
|
|
|
maxElements = CAT->getSize();
|
2009-01-24 00:54:12 +08:00
|
|
|
elementIndex.extOrTrunc(maxElements.getBitWidth());
|
2009-01-24 02:58:42 +08:00
|
|
|
elementIndex.setIsUnsigned(maxElements.isUnsigned());
|
2009-01-22 08:58:24 +08:00
|
|
|
maxElementsKnown = true;
|
|
|
|
}
|
|
|
|
|
2009-02-25 06:50:46 +08:00
|
|
|
QualType elementType = SemaRef.Context.getAsArrayType(DeclType)
|
2008-08-04 15:31:14 +08:00
|
|
|
->getElementType();
|
2009-01-22 08:58:24 +08:00
|
|
|
while (Index < IList->getNumInits()) {
|
|
|
|
Expr *Init = IList->getInit(Index);
|
|
|
|
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
|
2009-01-23 07:26:18 +08:00
|
|
|
// 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.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (CheckDesignatedInitializer(IList, DIE, 0,
|
2009-01-29 05:54:33 +08:00
|
|
|
DeclType, 0, &elementIndex, Index,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredList, StructuredIndex, true,
|
|
|
|
false)) {
|
2009-01-22 08:58:24 +08:00
|
|
|
hadError = true;
|
2009-01-23 07:26:18 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-01-24 00:54:12 +08:00
|
|
|
if (elementIndex.getBitWidth() > maxElements.getBitWidth())
|
|
|
|
maxElements.extend(elementIndex.getBitWidth());
|
|
|
|
else if (elementIndex.getBitWidth() < maxElements.getBitWidth())
|
|
|
|
elementIndex.extend(maxElements.getBitWidth());
|
2009-01-24 02:58:42 +08:00
|
|
|
elementIndex.setIsUnsigned(maxElements.isUnsigned());
|
2009-01-24 00:54:12 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// If the array is of incomplete type, keep track of the number of
|
|
|
|
// elements in the initializer.
|
|
|
|
if (!maxElementsKnown && elementIndex > maxElements)
|
|
|
|
maxElements = elementIndex;
|
2009-01-22 08:58:24 +08:00
|
|
|
|
|
|
|
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)
|
2008-05-02 06:18:59 +08:00
|
|
|
break;
|
2009-01-22 08:58:24 +08:00
|
|
|
|
|
|
|
// Check this element.
|
2009-01-29 08:39:20 +08:00
|
|
|
CheckSubElementType(IList, elementType, Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList, StructuredIndex);
|
2009-01-22 08:58:24 +08:00
|
|
|
++elementIndex;
|
|
|
|
|
|
|
|
// If the array is of incomplete type, keep track of the number of
|
|
|
|
// elements in the initializer.
|
|
|
|
if (!maxElementsKnown && elementIndex > maxElements)
|
|
|
|
maxElements = elementIndex;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2009-05-30 04:17:55 +08:00
|
|
|
if (!hadError && DeclType->isIncompleteArrayType()) {
|
2008-05-02 06:18:59 +08:00
|
|
|
// If this is an incomplete array type, the actual type needs to
|
2008-08-19 04:28:46 +08:00
|
|
|
// be calculated here.
|
2009-01-24 02:58:42 +08:00
|
|
|
llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
|
2009-01-22 08:58:24 +08:00
|
|
|
if (maxElements == Zero) {
|
2008-08-19 04:28:46 +08:00
|
|
|
// Sizing an array implicitly to zero is not allowed by ISO C,
|
|
|
|
// but is supported by GNU.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IList->getLocStart(),
|
2008-08-19 04:28:46 +08:00
|
|
|
diag::ext_typecheck_zero_array_size);
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2008-08-19 04:28:46 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements,
|
2008-08-19 04:28:46 +08:00
|
|
|
ArrayType::Normal, 0);
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
|
|
|
|
QualType DeclType,
|
2009-01-23 07:26:18 +08:00
|
|
|
RecordDecl::field_iterator Field,
|
2009-09-09 23:08:12 +08:00
|
|
|
bool SubobjectIsDesignatorContext,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2009-02-05 06:46:25 +08:00
|
|
|
unsigned &StructuredIndex,
|
|
|
|
bool TopLevelObject) {
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl* structDecl = DeclType->getAs<RecordType>()->getDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2008-05-20 03:16:24 +08:00
|
|
|
// 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;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-01-30 01:44:32 +08:00
|
|
|
|
|
|
|
if (DeclType->isUnionType() && IList->getNumInits() == 0) {
|
|
|
|
// Value-initialize the first named member of the union.
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
|
2009-06-30 10:36:12 +08:00
|
|
|
for (RecordDecl::field_iterator FieldEnd = RD->field_end();
|
2009-01-30 01:44:32 +08:00
|
|
|
Field != FieldEnd; ++Field) {
|
|
|
|
if (Field->getDeclName()) {
|
|
|
|
StructuredList->setInitializedFieldInUnion(*Field);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
// 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.
|
2009-07-30 05:53:49 +08:00
|
|
|
RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
|
2009-06-30 10:36:12 +08:00
|
|
|
RecordDecl::field_iterator FieldEnd = RD->field_end();
|
2009-02-13 03:00:39 +08:00
|
|
|
bool InitializedSomething = false;
|
2009-01-22 08:58:24 +08:00
|
|
|
while (Index < IList->getNumInits()) {
|
|
|
|
Expr *Init = IList->getInit(Index);
|
|
|
|
|
|
|
|
if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) {
|
2009-01-23 07:26:18 +08:00
|
|
|
// 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.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (CheckDesignatedInitializer(IList, DIE, 0,
|
2009-01-29 05:54:33 +08:00
|
|
|
DeclType, &Field, 0, Index,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredList, StructuredIndex,
|
|
|
|
true, TopLevelObject))
|
2009-01-22 08:58:24 +08:00
|
|
|
hadError = true;
|
|
|
|
|
2009-02-13 03:00:39 +08:00
|
|
|
InitializedSomething = true;
|
2009-01-22 08:58:24 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Field == FieldEnd) {
|
|
|
|
// We've run out of fields. We're done.
|
2008-12-12 00:49:14 +08:00
|
|
|
break;
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-02-13 03:00:39 +08:00
|
|
|
// We've already initialized a member of a union. We're done.
|
|
|
|
if (InitializedSomething && DeclType->isUnionType())
|
|
|
|
break;
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
// If we've hit the flexible array member at the end, we're done.
|
|
|
|
if (Field->getType()->isIncompleteArrayType())
|
2008-05-20 03:16:24 +08:00
|
|
|
break;
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-01-30 00:53:55 +08:00
|
|
|
if (Field->isUnnamedBitfield()) {
|
2009-01-29 05:54:33 +08:00
|
|
|
// Don't initialize unnamed bitfields, e.g. "int : 20;"
|
2009-01-22 08:58:24 +08:00
|
|
|
++Field;
|
2008-05-20 03:16:24 +08:00
|
|
|
continue;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-01-29 08:39:20 +08:00
|
|
|
CheckSubElementType(IList, Field->getType(), Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList, StructuredIndex);
|
2009-02-13 03:00:39 +08:00
|
|
|
InitializedSomething = true;
|
2009-01-30 00:53:55 +08:00
|
|
|
|
|
|
|
if (DeclType->isUnionType()) {
|
|
|
|
// Initialize the first field within the union.
|
|
|
|
StructuredList->setInitializedFieldInUnion(*Field);
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
|
|
|
++Field;
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
2008-12-12 00:49:14 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() ||
|
2009-03-20 08:32:56 +08:00
|
|
|
Index >= IList->getNumInits())
|
2009-02-05 06:46:25 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Handle GNU flexible array initializers.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (!TopLevelObject &&
|
2009-03-20 08:32:56 +08:00
|
|
|
(!isa<InitListExpr>(IList->getInit(Index)) ||
|
|
|
|
cast<InitListExpr>(IList->getInit(Index))->getNumInits() > 0)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
|
2009-02-05 06:46:25 +08:00
|
|
|
diag::err_flexible_array_init_nonempty)
|
|
|
|
<< IList->getInit(Index)->getSourceRange().getBegin();
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
|
2009-02-05 06:46:25 +08:00
|
|
|
<< *Field;
|
|
|
|
hadError = true;
|
2009-03-20 08:32:56 +08:00
|
|
|
++Index;
|
|
|
|
return;
|
|
|
|
} else {
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
|
2009-03-20 08:32:56 +08:00
|
|
|
diag::ext_flexible_array_init)
|
|
|
|
<< IList->getInit(Index)->getSourceRange().getBegin();
|
|
|
|
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
|
|
|
|
<< *Field;
|
2009-02-05 06:46:25 +08:00
|
|
|
}
|
|
|
|
|
2009-03-20 08:32:56 +08:00
|
|
|
if (isa<InitListExpr>(IList->getInit(Index)))
|
|
|
|
CheckSubElementType(IList, Field->getType(), Index, StructuredList,
|
|
|
|
StructuredIndex);
|
|
|
|
else
|
|
|
|
CheckImplicitInitList(IList, Field->getType(), Index, StructuredList,
|
|
|
|
StructuredIndex);
|
2008-05-02 06:18:59 +08:00
|
|
|
}
|
|
|
|
|
2009-04-15 14:41:24 +08:00
|
|
|
/// \brief Expand a field designator that refers to a member of an
|
|
|
|
/// anonymous struct or union into a series of field designators that
|
|
|
|
/// refers to the field within the appropriate subobject.
|
|
|
|
///
|
|
|
|
/// Field/FieldIndex will be updated to point to the (new)
|
|
|
|
/// currently-designated field.
|
|
|
|
static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
|
2009-09-09 23:08:12 +08:00
|
|
|
DesignatedInitExpr *DIE,
|
|
|
|
unsigned DesigIdx,
|
2009-04-15 14:41:24 +08:00
|
|
|
FieldDecl *Field,
|
|
|
|
RecordDecl::field_iterator &FieldIter,
|
|
|
|
unsigned &FieldIndex) {
|
|
|
|
typedef DesignatedInitExpr::Designator Designator;
|
|
|
|
|
|
|
|
// Build the path from the current object to the member of the
|
|
|
|
// anonymous struct/union (backwards).
|
|
|
|
llvm::SmallVector<FieldDecl *, 4> Path;
|
|
|
|
SemaRef.BuildAnonymousStructUnionMemberPath(Field, Path);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-04-15 14:41:24 +08:00
|
|
|
// Build the replacement designators.
|
|
|
|
llvm::SmallVector<Designator, 4> Replacements;
|
|
|
|
for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
|
|
|
|
FI = Path.rbegin(), FIEnd = Path.rend();
|
|
|
|
FI != FIEnd; ++FI) {
|
|
|
|
if (FI + 1 == FIEnd)
|
2009-09-09 23:08:12 +08:00
|
|
|
Replacements.push_back(Designator((IdentifierInfo *)0,
|
2009-04-15 14:41:24 +08:00
|
|
|
DIE->getDesignator(DesigIdx)->getDotLoc(),
|
|
|
|
DIE->getDesignator(DesigIdx)->getFieldLoc()));
|
|
|
|
else
|
|
|
|
Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
|
|
|
|
SourceLocation()));
|
|
|
|
Replacements.back().setField(*FI);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Expand the current designator into the set of replacement
|
|
|
|
// designators, so we have a full subobject path down to where the
|
|
|
|
// member of the anonymous struct/union is actually stored.
|
2009-09-09 23:08:12 +08:00
|
|
|
DIE->ExpandDesignator(DesigIdx, &Replacements[0],
|
2009-04-15 14:41:24 +08:00
|
|
|
&Replacements[0] + Replacements.size());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-04-15 14:41:24 +08:00
|
|
|
// Update FieldIter/FieldIndex;
|
|
|
|
RecordDecl *Record = cast<RecordDecl>(Path.back()->getDeclContext());
|
2009-06-30 10:36:12 +08:00
|
|
|
FieldIter = Record->field_begin();
|
2009-04-15 14:41:24 +08:00
|
|
|
FieldIndex = 0;
|
2009-06-30 10:36:12 +08:00
|
|
|
for (RecordDecl::field_iterator FEnd = Record->field_end();
|
2009-04-15 14:41:24 +08:00
|
|
|
FieldIter != FEnd; ++FieldIter) {
|
|
|
|
if (FieldIter->isUnnamedBitfield())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (*FieldIter == Path.back())
|
|
|
|
return;
|
|
|
|
|
|
|
|
++FieldIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(false && "Unable to find anonymous struct/union field");
|
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
/// @brief Check the well-formedness of a C99 designated initializer.
|
|
|
|
///
|
|
|
|
/// Determines whether the designated initializer @p DIE, which
|
|
|
|
/// resides at the given @p Index within the initializer list @p
|
|
|
|
/// IList, is well-formed for a current object of type @p DeclType
|
|
|
|
/// (C99 6.7.8). The actual subobject that this designator refers to
|
2009-09-09 23:08:12 +08:00
|
|
|
/// within the current subobject is returned in either
|
2009-01-29 05:54:33 +08:00
|
|
|
/// @p NextField or @p NextElementIndex (whichever is appropriate).
|
2009-01-22 08:58:24 +08:00
|
|
|
///
|
|
|
|
/// @param IList The initializer list in which this designated
|
|
|
|
/// initializer occurs.
|
|
|
|
///
|
2009-04-15 12:56:10 +08:00
|
|
|
/// @param DIE The designated initializer expression.
|
|
|
|
///
|
|
|
|
/// @param DesigIdx The index of the current designator.
|
2009-01-22 08:58:24 +08:00
|
|
|
///
|
|
|
|
/// @param DeclType The type of the "current object" (C99 6.7.8p17),
|
|
|
|
/// into which the designation in @p DIE should refer.
|
|
|
|
///
|
2009-01-23 07:26:18 +08:00
|
|
|
/// @param NextField If non-NULL and the first designator in @p DIE is
|
|
|
|
/// a field, this will be set to the field declaration corresponding
|
|
|
|
/// to the field named by the designator.
|
2009-01-22 08:58:24 +08:00
|
|
|
///
|
2009-01-23 07:26:18 +08:00
|
|
|
/// @param NextElementIndex If non-NULL and the first designator in @p
|
|
|
|
/// DIE is an array designator or GNU array-range designator, this
|
|
|
|
/// will be set to the last index initialized by this designator.
|
2009-01-22 08:58:24 +08:00
|
|
|
///
|
|
|
|
/// @param Index Index into @p IList where the designated initializer
|
|
|
|
/// @p DIE occurs.
|
|
|
|
///
|
2009-01-29 05:54:33 +08:00
|
|
|
/// @param StructuredList The initializer list expression that
|
|
|
|
/// describes all of the subobject initializers in the order they'll
|
|
|
|
/// actually be initialized.
|
|
|
|
///
|
2009-01-22 08:58:24 +08:00
|
|
|
/// @returns true if there was an error, false otherwise.
|
2009-09-09 23:08:12 +08:00
|
|
|
bool
|
2009-01-23 07:26:18 +08:00
|
|
|
InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
|
2009-09-09 23:08:12 +08:00
|
|
|
DesignatedInitExpr *DIE,
|
2009-04-15 12:56:10 +08:00
|
|
|
unsigned DesigIdx,
|
2009-01-23 07:26:18 +08:00
|
|
|
QualType &CurrentObjectType,
|
|
|
|
RecordDecl::field_iterator *NextField,
|
|
|
|
llvm::APSInt *NextElementIndex,
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned &Index,
|
|
|
|
InitListExpr *StructuredList,
|
2009-01-29 07:36:17 +08:00
|
|
|
unsigned &StructuredIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
bool FinishSubobjectInit,
|
|
|
|
bool TopLevelObject) {
|
2009-04-15 12:56:10 +08:00
|
|
|
if (DesigIdx == DIE->size()) {
|
2009-01-23 07:26:18 +08:00
|
|
|
// Check the actual initialization for the designated object type.
|
|
|
|
bool prevHadError = hadError;
|
2009-01-29 08:39:20 +08:00
|
|
|
|
|
|
|
// Temporarily remove the designator expression from the
|
|
|
|
// initializer list that the child calls see, so that we don't try
|
|
|
|
// to re-process the designator.
|
|
|
|
unsigned OldIndex = Index;
|
|
|
|
IList->setInit(OldIndex, DIE->getInit());
|
|
|
|
|
|
|
|
CheckSubElementType(IList, CurrentObjectType, Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList, StructuredIndex);
|
2009-01-29 08:39:20 +08:00
|
|
|
|
|
|
|
// Restore the designated initializer expression in the syntactic
|
|
|
|
// form of the initializer list.
|
|
|
|
if (IList->getInit(OldIndex) != DIE->getInit())
|
|
|
|
DIE->setInit(IList->getInit(OldIndex));
|
|
|
|
IList->setInit(OldIndex, DIE);
|
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
return hadError && !prevHadError;
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-04-15 12:56:10 +08:00
|
|
|
bool IsFirstDesignator = (DesigIdx == 0);
|
2009-09-09 23:08:12 +08:00
|
|
|
assert((IsFirstDesignator || StructuredList) &&
|
2009-01-29 05:54:33 +08:00
|
|
|
"Need a non-designated initializer list to start from");
|
|
|
|
|
2009-04-15 12:56:10 +08:00
|
|
|
DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
|
2009-01-29 05:54:33 +08:00
|
|
|
// Determine the structural initializer list that corresponds to the
|
|
|
|
// current subobject.
|
|
|
|
StructuredList = IsFirstDesignator? SyntacticToSemantic[IList]
|
2009-09-09 23:08:12 +08:00
|
|
|
: getStructuredSubobjectInit(IList, Index, CurrentObjectType,
|
2009-03-02 01:12:46 +08:00
|
|
|
StructuredList, StructuredIndex,
|
2009-01-29 05:54:33 +08:00
|
|
|
SourceRange(D->getStartLocation(),
|
|
|
|
DIE->getSourceRange().getEnd()));
|
|
|
|
assert(StructuredList && "Expected a structured initializer list");
|
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
if (D->isFieldDesignator()) {
|
|
|
|
// C99 6.7.8p7:
|
|
|
|
//
|
|
|
|
// If a designator has the form
|
|
|
|
//
|
|
|
|
// . identifier
|
|
|
|
//
|
|
|
|
// then the current object (defined below) shall have
|
|
|
|
// structure or union type and the identifier shall be the
|
2009-09-09 23:08:12 +08:00
|
|
|
// name of a member of that type.
|
2009-07-30 05:53:49 +08:00
|
|
|
const RecordType *RT = CurrentObjectType->getAs<RecordType>();
|
2009-01-23 07:26:18 +08:00
|
|
|
if (!RT) {
|
|
|
|
SourceLocation Loc = D->getDotLoc();
|
|
|
|
if (Loc.isInvalid())
|
|
|
|
Loc = D->getFieldLoc();
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
|
|
|
|
<< SemaRef.getLangOptions().CPlusPlus << CurrentObjectType;
|
2009-01-23 07:26:18 +08:00
|
|
|
++Index;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Note: we perform a linear search of the fields here, despite
|
|
|
|
// the fact that we have a faster lookup method, because we always
|
|
|
|
// need to compute the field's index.
|
2009-04-15 14:41:24 +08:00
|
|
|
FieldDecl *KnownField = D->getField();
|
2009-01-23 07:26:18 +08:00
|
|
|
IdentifierInfo *FieldName = D->getFieldName();
|
2009-01-29 05:54:33 +08:00
|
|
|
unsigned FieldIndex = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
RecordDecl::field_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
Field = RT->getDecl()->field_begin(),
|
|
|
|
FieldEnd = RT->getDecl()->field_end();
|
2009-01-29 05:54:33 +08:00
|
|
|
for (; Field != FieldEnd; ++Field) {
|
|
|
|
if (Field->isUnnamedBitfield())
|
|
|
|
continue;
|
|
|
|
|
2009-04-15 14:41:24 +08:00
|
|
|
if (KnownField == *Field || Field->getIdentifier() == FieldName)
|
2009-01-29 05:54:33 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
++FieldIndex;
|
2009-01-23 07:26:18 +08:00
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
if (Field == FieldEnd) {
|
2009-04-15 14:41:24 +08:00
|
|
|
// There was no normal field in the struct with the designated
|
|
|
|
// name. Perform another lookup for this name, which may find
|
|
|
|
// something that we can't designate (e.g., a member function),
|
|
|
|
// may find nothing, or may find a member of an anonymous
|
2009-09-09 23:08:12 +08:00
|
|
|
// struct/union.
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName);
|
2009-01-29 05:54:33 +08:00
|
|
|
if (Lookup.first == Lookup.second) {
|
|
|
|
// Name lookup didn't find anything.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
|
2009-01-29 05:54:33 +08:00
|
|
|
<< FieldName << CurrentObjectType;
|
2009-04-15 14:41:24 +08:00
|
|
|
++Index;
|
|
|
|
return true;
|
|
|
|
} else if (!KnownField && isa<FieldDecl>(*Lookup.first) &&
|
|
|
|
cast<RecordDecl>((*Lookup.first)->getDeclContext())
|
|
|
|
->isAnonymousStructOrUnion()) {
|
|
|
|
// Handle an field designator that refers to a member of an
|
|
|
|
// anonymous struct or union.
|
2009-09-09 23:08:12 +08:00
|
|
|
ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx,
|
2009-04-15 14:41:24 +08:00
|
|
|
cast<FieldDecl>(*Lookup.first),
|
|
|
|
Field, FieldIndex);
|
2009-04-17 01:49:48 +08:00
|
|
|
D = DIE->getDesignator(DesigIdx);
|
2009-01-29 05:54:33 +08:00
|
|
|
} else {
|
|
|
|
// Name lookup found something, but it wasn't a field.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
|
2009-01-29 05:54:33 +08:00
|
|
|
<< FieldName;
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag((*Lookup.first)->getLocation(),
|
2009-01-29 05:54:33 +08:00
|
|
|
diag::note_field_designator_found);
|
2009-04-17 01:49:48 +08:00
|
|
|
++Index;
|
|
|
|
return true;
|
2009-04-15 14:41:24 +08:00
|
|
|
}
|
|
|
|
} else if (!KnownField &&
|
|
|
|
cast<RecordDecl>((*Field)->getDeclContext())
|
2009-01-29 05:54:33 +08:00
|
|
|
->isAnonymousStructOrUnion()) {
|
2009-04-15 14:41:24 +08:00
|
|
|
ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, *Field,
|
|
|
|
Field, FieldIndex);
|
|
|
|
D = DIE->getDesignator(DesigIdx);
|
2009-01-23 07:26:18 +08:00
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
|
|
|
|
// All of the fields of a union are located at the same place in
|
|
|
|
// the initializer list.
|
2009-01-30 00:53:55 +08:00
|
|
|
if (RT->getDecl()->isUnion()) {
|
2009-01-29 05:54:33 +08:00
|
|
|
FieldIndex = 0;
|
2009-01-30 00:53:55 +08:00
|
|
|
StructuredList->setInitializedFieldInUnion(*Field);
|
|
|
|
}
|
2009-01-29 05:54:33 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// Update the designator with the field declaration.
|
2009-01-29 05:54:33 +08:00
|
|
|
D->setField(*Field);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Make sure that our non-designated initializer list has space
|
|
|
|
// for a subobject corresponding to this field.
|
|
|
|
if (FieldIndex >= StructuredList->getNumInits())
|
2009-02-25 06:50:46 +08:00
|
|
|
StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);
|
2009-01-29 05:54:33 +08:00
|
|
|
|
2009-02-05 06:46:25 +08:00
|
|
|
// This designator names a flexible array member.
|
|
|
|
if (Field->getType()->isIncompleteArrayType()) {
|
|
|
|
bool Invalid = false;
|
2009-04-15 12:56:10 +08:00
|
|
|
if ((DesigIdx + 1) != DIE->size()) {
|
2009-02-05 06:46:25 +08:00
|
|
|
// We can't designate an object within the flexible array
|
|
|
|
// member (because GCC doesn't allow it).
|
2009-09-09 23:08:12 +08:00
|
|
|
DesignatedInitExpr::Designator *NextD
|
2009-04-15 12:56:10 +08:00
|
|
|
= DIE->getDesignator(DesigIdx + 1);
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(NextD->getStartLocation(),
|
2009-02-05 06:46:25 +08:00
|
|
|
diag::err_designator_into_flexible_array_member)
|
2009-09-09 23:08:12 +08:00
|
|
|
<< SourceRange(NextD->getStartLocation(),
|
2009-02-05 06:46:25 +08:00
|
|
|
DIE->getSourceRange().getEnd());
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
|
2009-02-05 06:46:25 +08:00
|
|
|
<< *Field;
|
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hadError && !isa<InitListExpr>(DIE->getInit())) {
|
|
|
|
// The initializer is not an initializer list.
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(DIE->getInit()->getSourceRange().getBegin(),
|
2009-02-05 06:46:25 +08:00
|
|
|
diag::err_flexible_array_init_needs_braces)
|
|
|
|
<< DIE->getInit()->getSourceRange();
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
|
2009-02-05 06:46:25 +08:00
|
|
|
<< *Field;
|
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle GNU flexible array initializers.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (!Invalid && !TopLevelObject &&
|
2009-02-05 06:46:25 +08:00
|
|
|
cast<InitListExpr>(DIE->getInit())->getNumInits() > 0) {
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(DIE->getSourceRange().getBegin(),
|
2009-02-05 06:46:25 +08:00
|
|
|
diag::err_flexible_array_init_nonempty)
|
|
|
|
<< DIE->getSourceRange().getBegin();
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
|
2009-02-05 06:46:25 +08:00
|
|
|
<< *Field;
|
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Invalid) {
|
|
|
|
++Index;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the array.
|
|
|
|
bool prevHadError = hadError;
|
|
|
|
unsigned newStructuredIndex = FieldIndex;
|
|
|
|
unsigned OldIndex = Index;
|
|
|
|
IList->setInit(Index, DIE->getInit());
|
2009-09-09 23:08:12 +08:00
|
|
|
CheckSubElementType(IList, Field->getType(), Index,
|
2009-02-05 06:46:25 +08:00
|
|
|
StructuredList, newStructuredIndex);
|
|
|
|
IList->setInit(OldIndex, DIE);
|
|
|
|
if (hadError && !prevHadError) {
|
|
|
|
++Field;
|
|
|
|
++FieldIndex;
|
|
|
|
if (NextField)
|
|
|
|
*NextField = Field;
|
|
|
|
StructuredIndex = FieldIndex;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Recurse to check later designated subobjects.
|
|
|
|
QualType FieldType = (*Field)->getType();
|
|
|
|
unsigned newStructuredIndex = FieldIndex;
|
2009-04-15 12:56:10 +08:00
|
|
|
if (CheckDesignatedInitializer(IList, DIE, DesigIdx + 1, FieldType, 0, 0,
|
|
|
|
Index, StructuredList, newStructuredIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
true, false))
|
|
|
|
return true;
|
|
|
|
}
|
2009-01-23 07:26:18 +08:00
|
|
|
|
|
|
|
// Find the position of the next field to be initialized in this
|
|
|
|
// subobject.
|
|
|
|
++Field;
|
2009-01-29 05:54:33 +08:00
|
|
|
++FieldIndex;
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// If this the first designator, our caller will continue checking
|
|
|
|
// the rest of this struct/class/union subobject.
|
|
|
|
if (IsFirstDesignator) {
|
|
|
|
if (NextField)
|
|
|
|
*NextField = Field;
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredIndex = FieldIndex;
|
2009-01-23 07:26:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-29 07:36:17 +08:00
|
|
|
if (!FinishSubobjectInit)
|
|
|
|
return false;
|
|
|
|
|
2009-04-15 14:41:24 +08:00
|
|
|
// We've already initialized something in the union; we're done.
|
|
|
|
if (RT->getDecl()->isUnion())
|
|
|
|
return hadError;
|
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// Check the remaining fields within this class/struct/union subobject.
|
|
|
|
bool prevHadError = hadError;
|
2009-01-29 05:54:33 +08:00
|
|
|
CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index,
|
|
|
|
StructuredList, FieldIndex);
|
2009-01-23 07:26:18 +08:00
|
|
|
return hadError && !prevHadError;
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// C99 6.7.8p6:
|
|
|
|
//
|
|
|
|
// If a designator has the form
|
|
|
|
//
|
|
|
|
// [ constant-expression ]
|
|
|
|
//
|
|
|
|
// then the current object (defined below) shall have array
|
|
|
|
// type and the expression shall be an integer constant
|
|
|
|
// expression. If the array is of unknown size, any
|
|
|
|
// nonnegative value is valid.
|
|
|
|
//
|
|
|
|
// Additionally, cope with the GNU extension that permits
|
|
|
|
// designators of the form
|
|
|
|
//
|
|
|
|
// [ constant-expression ... constant-expression ]
|
2009-02-25 06:50:46 +08:00
|
|
|
const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType);
|
2009-01-23 07:26:18 +08:00
|
|
|
if (!AT) {
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
|
2009-01-23 07:26:18 +08:00
|
|
|
<< CurrentObjectType;
|
|
|
|
++Index;
|
|
|
|
return true;
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
Expr *IndexExpr = 0;
|
2009-01-29 07:36:17 +08:00
|
|
|
llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
|
|
|
|
if (D->isArrayDesignator()) {
|
2009-01-23 07:26:18 +08:00
|
|
|
IndexExpr = DIE->getArrayIndex(*D);
|
2009-04-26 05:59:05 +08:00
|
|
|
DesignatedStartIndex = IndexExpr->EvaluateAsInt(SemaRef.Context);
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedEndIndex = DesignatedStartIndex;
|
|
|
|
} else {
|
2009-01-23 07:26:18 +08:00
|
|
|
assert(D->isArrayRangeDesignator() && "Need array-range designator");
|
2009-04-26 05:59:05 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
DesignatedStartIndex =
|
2009-04-26 05:59:05 +08:00
|
|
|
DIE->getArrayRangeStart(*D)->EvaluateAsInt(SemaRef.Context);
|
2009-09-09 23:08:12 +08:00
|
|
|
DesignatedEndIndex =
|
2009-04-26 05:59:05 +08:00
|
|
|
DIE->getArrayRangeEnd(*D)->EvaluateAsInt(SemaRef.Context);
|
2009-01-23 07:26:18 +08:00
|
|
|
IndexExpr = DIE->getArrayRangeEnd(*D);
|
2009-01-29 07:36:17 +08:00
|
|
|
|
2009-04-26 05:59:05 +08:00
|
|
|
if (DesignatedStartIndex.getZExtValue() !=DesignatedEndIndex.getZExtValue())
|
2009-01-30 03:42:23 +08:00
|
|
|
FullyStructuredList->sawArrayRangeDesignator();
|
2009-01-23 07:26:18 +08:00
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
if (isa<ConstantArrayType>(AT)) {
|
|
|
|
llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
|
|
|
|
DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
|
|
|
|
DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
|
|
|
|
DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
|
|
|
|
if (DesignatedEndIndex >= MaxElements) {
|
2009-02-25 06:50:46 +08:00
|
|
|
SemaRef.Diag(IndexExpr->getSourceRange().getBegin(),
|
2009-01-23 07:26:18 +08:00
|
|
|
diag::err_array_designator_too_large)
|
2009-01-29 07:36:17 +08:00
|
|
|
<< DesignatedEndIndex.toString(10) << MaxElements.toString(10)
|
2009-01-23 07:26:18 +08:00
|
|
|
<< IndexExpr->getSourceRange();
|
|
|
|
++Index;
|
|
|
|
return true;
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
2009-01-29 07:36:17 +08:00
|
|
|
} else {
|
|
|
|
// Make sure the bit-widths and signedness match.
|
|
|
|
if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth())
|
|
|
|
DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
|
2009-04-26 05:59:05 +08:00
|
|
|
else if (DesignatedStartIndex.getBitWidth() <
|
|
|
|
DesignatedEndIndex.getBitWidth())
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
|
|
|
|
DesignatedStartIndex.setIsUnsigned(true);
|
|
|
|
DesignatedEndIndex.setIsUnsigned(true);
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Make sure that our non-designated initializer list has space
|
|
|
|
// for a subobject corresponding to this array element.
|
2009-01-29 07:36:17 +08:00
|
|
|
if (DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
|
2009-09-09 23:08:12 +08:00
|
|
|
StructuredList->resizeInits(SemaRef.Context,
|
2009-01-29 07:36:17 +08:00
|
|
|
DesignatedEndIndex.getZExtValue() + 1);
|
|
|
|
|
|
|
|
// Repeatedly perform subobject initializations in the range
|
|
|
|
// [DesignatedStartIndex, DesignatedEndIndex].
|
|
|
|
|
|
|
|
// Move to the next designator
|
|
|
|
unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
|
|
|
|
unsigned OldIndex = Index;
|
|
|
|
while (DesignatedStartIndex <= DesignatedEndIndex) {
|
|
|
|
// Recurse to check later designated subobjects.
|
|
|
|
QualType ElementType = AT->getElementType();
|
|
|
|
Index = OldIndex;
|
2009-04-15 12:56:10 +08:00
|
|
|
if (CheckDesignatedInitializer(IList, DIE, DesigIdx + 1, ElementType, 0, 0,
|
|
|
|
Index, StructuredList, ElementIndex,
|
2009-02-05 06:46:25 +08:00
|
|
|
(DesignatedStartIndex == DesignatedEndIndex),
|
|
|
|
false))
|
2009-01-29 07:36:17 +08:00
|
|
|
return true;
|
2009-01-23 07:26:18 +08:00
|
|
|
|
2009-01-29 07:36:17 +08:00
|
|
|
// Move to the next index in the array that we'll be initializing.
|
|
|
|
++DesignatedStartIndex;
|
|
|
|
ElementIndex = DesignatedStartIndex.getZExtValue();
|
|
|
|
}
|
2009-01-23 07:26:18 +08:00
|
|
|
|
|
|
|
// If this the first designator, our caller will continue checking
|
|
|
|
// the rest of this array subobject.
|
|
|
|
if (IsFirstDesignator) {
|
|
|
|
if (NextElementIndex)
|
2009-01-29 07:36:17 +08:00
|
|
|
*NextElementIndex = DesignatedStartIndex;
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredIndex = ElementIndex;
|
2009-01-23 07:26:18 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 07:36:17 +08:00
|
|
|
if (!FinishSubobjectInit)
|
|
|
|
return false;
|
|
|
|
|
2009-01-23 07:26:18 +08:00
|
|
|
// Check the remaining elements within this array subobject.
|
2009-01-22 08:58:24 +08:00
|
|
|
bool prevHadError = hadError;
|
2009-02-10 03:45:19 +08:00
|
|
|
CheckArrayType(IList, CurrentObjectType, DesignatedStartIndex, false, Index,
|
2009-01-29 05:54:33 +08:00
|
|
|
StructuredList, ElementIndex);
|
2009-09-09 23:08:12 +08:00
|
|
|
return hadError && !prevHadError;
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Get the structured initializer list for a subobject of type
|
|
|
|
// @p CurrentObjectType.
|
|
|
|
InitListExpr *
|
|
|
|
InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
|
|
|
|
QualType CurrentObjectType,
|
|
|
|
InitListExpr *StructuredList,
|
|
|
|
unsigned StructuredIndex,
|
|
|
|
SourceRange InitRange) {
|
|
|
|
Expr *ExistingInit = 0;
|
|
|
|
if (!StructuredList)
|
|
|
|
ExistingInit = SyntacticToSemantic[IList];
|
|
|
|
else if (StructuredIndex < StructuredList->getNumInits())
|
|
|
|
ExistingInit = StructuredList->getInit(StructuredIndex);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit))
|
|
|
|
return Result;
|
|
|
|
|
|
|
|
if (ExistingInit) {
|
|
|
|
// We are creating an initializer list that initializes the
|
|
|
|
// subobjects of the current object, but there was already an
|
|
|
|
// initialization that completely initialized the current
|
|
|
|
// subobject, e.g., by a compound literal:
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2009-01-29 05:54:33 +08:00
|
|
|
// struct X { int a, b; };
|
|
|
|
// struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 };
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2009-01-29 05:54:33 +08:00
|
|
|
// Here, xs[0].a == 0 and xs[0].b == 3, since the second,
|
|
|
|
// designated initializer re-initializes the whole
|
|
|
|
// subobject [0], overwriting previous initializers.
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(InitRange.getBegin(),
|
2009-03-02 01:12:46 +08:00
|
|
|
diag::warn_subobject_initializer_overrides)
|
2009-01-29 05:54:33 +08:00
|
|
|
<< InitRange;
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(ExistingInit->getSourceRange().getBegin(),
|
2009-01-29 05:54:33 +08:00
|
|
|
diag::note_previous_initializer)
|
2009-01-29 07:43:32 +08:00
|
|
|
<< /*FIXME:has side effects=*/0
|
2009-01-29 05:54:33 +08:00
|
|
|
<< ExistingInit->getSourceRange();
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
InitListExpr *Result
|
|
|
|
= new (SemaRef.Context) InitListExpr(InitRange.getBegin(), 0, 0,
|
2009-03-02 01:12:46 +08:00
|
|
|
InitRange.getEnd());
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
Result->setType(CurrentObjectType);
|
|
|
|
|
2009-03-21 07:58:33 +08:00
|
|
|
// Pre-allocate storage for the structured initializer list.
|
|
|
|
unsigned NumElements = 0;
|
2009-03-22 02:13:52 +08:00
|
|
|
unsigned NumInits = 0;
|
|
|
|
if (!StructuredList)
|
|
|
|
NumInits = IList->getNumInits();
|
|
|
|
else if (Index < IList->getNumInits()) {
|
|
|
|
if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index)))
|
|
|
|
NumInits = SubList->getNumInits();
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const ArrayType *AType
|
2009-03-21 07:58:33 +08:00
|
|
|
= SemaRef.Context.getAsArrayType(CurrentObjectType)) {
|
|
|
|
if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) {
|
|
|
|
NumElements = CAType->getSize().getZExtValue();
|
|
|
|
// Simple heuristic so that we don't allocate a very large
|
|
|
|
// initializer with many empty entries at the end.
|
2009-03-22 02:13:52 +08:00
|
|
|
if (NumInits && NumElements > NumInits)
|
2009-03-21 07:58:33 +08:00
|
|
|
NumElements = 0;
|
|
|
|
}
|
2009-09-22 07:43:11 +08:00
|
|
|
} else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>())
|
2009-03-21 07:58:33 +08:00
|
|
|
NumElements = VType->getNumElements();
|
2009-07-30 05:53:49 +08:00
|
|
|
else if (const RecordType *RType = CurrentObjectType->getAs<RecordType>()) {
|
2009-03-21 07:58:33 +08:00
|
|
|
RecordDecl *RDecl = RType->getDecl();
|
|
|
|
if (RDecl->isUnion())
|
|
|
|
NumElements = 1;
|
|
|
|
else
|
2009-09-09 23:08:12 +08:00
|
|
|
NumElements = std::distance(RDecl->field_begin(),
|
2009-06-30 10:36:12 +08:00
|
|
|
RDecl->field_end());
|
2009-03-21 07:58:33 +08:00
|
|
|
}
|
|
|
|
|
2009-03-22 02:13:52 +08:00
|
|
|
if (NumElements < NumInits)
|
2009-03-21 07:58:33 +08:00
|
|
|
NumElements = IList->getNumInits();
|
|
|
|
|
|
|
|
Result->reserveInits(NumElements);
|
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
// Link this new initializer list into the structured initializer
|
|
|
|
// lists.
|
|
|
|
if (StructuredList)
|
|
|
|
StructuredList->updateInit(StructuredIndex, Result);
|
|
|
|
else {
|
|
|
|
Result->setSyntacticForm(IList);
|
|
|
|
SyntacticToSemantic[IList] = Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Update the initializer at index @p StructuredIndex within the
|
|
|
|
/// structured initializer list to the value @p expr.
|
|
|
|
void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList,
|
|
|
|
unsigned &StructuredIndex,
|
|
|
|
Expr *expr) {
|
|
|
|
// No structured initializer list to update
|
|
|
|
if (!StructuredList)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Expr *PrevInit = StructuredList->updateInit(StructuredIndex, expr)) {
|
|
|
|
// This initializer overwrites a previous initializer. Warn.
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(expr->getSourceRange().getBegin(),
|
2009-01-29 05:54:33 +08:00
|
|
|
diag::warn_initializer_overrides)
|
|
|
|
<< expr->getSourceRange();
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(PrevInit->getSourceRange().getBegin(),
|
2009-01-29 05:54:33 +08:00
|
|
|
diag::note_previous_initializer)
|
2009-01-29 07:43:32 +08:00
|
|
|
<< /*FIXME:has side effects=*/0
|
2009-01-29 05:54:33 +08:00
|
|
|
<< PrevInit->getSourceRange();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-01-29 05:54:33 +08:00
|
|
|
++StructuredIndex;
|
|
|
|
}
|
|
|
|
|
2009-01-22 08:58:24 +08:00
|
|
|
/// Check that the given Index expression is a valid array designator
|
|
|
|
/// value. This is essentailly just a wrapper around
|
2009-04-26 05:59:05 +08:00
|
|
|
/// VerifyIntegerConstantExpression that also checks for negative values
|
2009-01-22 08:58:24 +08:00
|
|
|
/// and produces a reasonable diagnostic if there is a
|
|
|
|
/// failure. Returns true if there was an error, false otherwise. If
|
|
|
|
/// everything went okay, Value will receive the value of the constant
|
|
|
|
/// expression.
|
2009-09-09 23:08:12 +08:00
|
|
|
static bool
|
2009-04-26 05:59:05 +08:00
|
|
|
CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
|
2009-01-22 08:58:24 +08:00
|
|
|
SourceLocation Loc = Index->getSourceRange().getBegin();
|
|
|
|
|
|
|
|
// Make sure this is an integer constant expression.
|
2009-04-26 05:59:05 +08:00
|
|
|
if (S.VerifyIntegerConstantExpression(Index, &Value))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (Value.isSigned() && Value.isNegative())
|
|
|
|
return S.Diag(Loc, diag::err_array_designator_negative)
|
2009-01-22 08:58:24 +08:00
|
|
|
<< Value.toString(10) << Index->getSourceRange();
|
|
|
|
|
2009-01-24 05:04:18 +08:00
|
|
|
Value.setIsUnsigned(true);
|
2009-01-22 08:58:24 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
|
|
|
|
SourceLocation Loc,
|
2009-03-28 08:41:23 +08:00
|
|
|
bool GNUSyntax,
|
2009-01-22 08:58:24 +08:00
|
|
|
OwningExprResult Init) {
|
|
|
|
typedef DesignatedInitExpr::Designator ASTDesignator;
|
|
|
|
|
|
|
|
bool Invalid = false;
|
|
|
|
llvm::SmallVector<ASTDesignator, 32> Designators;
|
|
|
|
llvm::SmallVector<Expr *, 32> InitExpressions;
|
|
|
|
|
|
|
|
// Build designators and check array designator expressions.
|
|
|
|
for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
|
|
|
|
const Designator &D = Desig.getDesignator(Idx);
|
|
|
|
switch (D.getKind()) {
|
|
|
|
case Designator::FieldDesignator:
|
2009-09-09 23:08:12 +08:00
|
|
|
Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(),
|
2009-01-22 08:58:24 +08:00
|
|
|
D.getFieldLoc()));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Designator::ArrayDesignator: {
|
|
|
|
Expr *Index = static_cast<Expr *>(D.getArrayIndex());
|
|
|
|
llvm::APSInt IndexValue;
|
2009-05-22 07:17:49 +08:00
|
|
|
if (!Index->isTypeDependent() &&
|
|
|
|
!Index->isValueDependent() &&
|
|
|
|
CheckArrayDesignatorExpr(*this, Index, IndexValue))
|
2009-01-22 08:58:24 +08:00
|
|
|
Invalid = true;
|
|
|
|
else {
|
|
|
|
Designators.push_back(ASTDesignator(InitExpressions.size(),
|
2009-09-09 23:08:12 +08:00
|
|
|
D.getLBracketLoc(),
|
2009-01-22 08:58:24 +08:00
|
|
|
D.getRBracketLoc()));
|
|
|
|
InitExpressions.push_back(Index);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case Designator::ArrayRangeDesignator: {
|
|
|
|
Expr *StartIndex = static_cast<Expr *>(D.getArrayRangeStart());
|
|
|
|
Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd());
|
|
|
|
llvm::APSInt StartValue;
|
|
|
|
llvm::APSInt EndValue;
|
2009-05-22 07:17:49 +08:00
|
|
|
bool StartDependent = StartIndex->isTypeDependent() ||
|
|
|
|
StartIndex->isValueDependent();
|
|
|
|
bool EndDependent = EndIndex->isTypeDependent() ||
|
|
|
|
EndIndex->isValueDependent();
|
|
|
|
if ((!StartDependent &&
|
|
|
|
CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) ||
|
|
|
|
(!EndDependent &&
|
|
|
|
CheckArrayDesignatorExpr(*this, EndIndex, EndValue)))
|
2009-01-22 08:58:24 +08:00
|
|
|
Invalid = true;
|
2009-01-24 06:22:29 +08:00
|
|
|
else {
|
|
|
|
// Make sure we're comparing values with the same bit width.
|
2009-05-22 07:17:49 +08:00
|
|
|
if (StartDependent || EndDependent) {
|
|
|
|
// Nothing to compute.
|
|
|
|
} else if (StartValue.getBitWidth() > EndValue.getBitWidth())
|
2009-01-24 06:22:29 +08:00
|
|
|
EndValue.extend(StartValue.getBitWidth());
|
|
|
|
else if (StartValue.getBitWidth() < EndValue.getBitWidth())
|
|
|
|
StartValue.extend(EndValue.getBitWidth());
|
|
|
|
|
2009-05-22 07:30:39 +08:00
|
|
|
if (!StartDependent && !EndDependent && EndValue < StartValue) {
|
2009-01-24 06:22:29 +08:00
|
|
|
Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range)
|
2009-09-09 23:08:12 +08:00
|
|
|
<< StartValue.toString(10) << EndValue.toString(10)
|
2009-01-24 06:22:29 +08:00
|
|
|
<< StartIndex->getSourceRange() << EndIndex->getSourceRange();
|
|
|
|
Invalid = true;
|
|
|
|
} else {
|
|
|
|
Designators.push_back(ASTDesignator(InitExpressions.size(),
|
2009-09-09 23:08:12 +08:00
|
|
|
D.getLBracketLoc(),
|
2009-01-24 06:22:29 +08:00
|
|
|
D.getEllipsisLoc(),
|
|
|
|
D.getRBracketLoc()));
|
|
|
|
InitExpressions.push_back(StartIndex);
|
|
|
|
InitExpressions.push_back(EndIndex);
|
|
|
|
}
|
2009-01-22 08:58:24 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Invalid || Init.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
// Clear out the expressions within the designation.
|
|
|
|
Desig.ClearExprs(*this);
|
|
|
|
|
|
|
|
DesignatedInitExpr *DIE
|
2009-05-21 17:52:38 +08:00
|
|
|
= DesignatedInitExpr::Create(Context,
|
|
|
|
Designators.data(), Designators.size(),
|
|
|
|
InitExpressions.data(), InitExpressions.size(),
|
2009-05-02 03:49:17 +08:00
|
|
|
Loc, GNUSyntax, Init.takeAs<Expr>());
|
2009-01-22 08:58:24 +08:00
|
|
|
return Owned(DIE);
|
|
|
|
}
|
2009-01-29 08:45:39 +08:00
|
|
|
|
|
|
|
bool Sema::CheckInitList(InitListExpr *&InitList, QualType &DeclType) {
|
2009-02-25 06:50:46 +08:00
|
|
|
InitListChecker CheckInitList(*this, InitList, DeclType);
|
2009-01-29 08:45:39 +08:00
|
|
|
if (!CheckInitList.HadError())
|
|
|
|
InitList = CheckInitList.getFullyStructuredList();
|
|
|
|
|
|
|
|
return CheckInitList.HadError();
|
|
|
|
}
|
2009-02-03 01:43:21 +08:00
|
|
|
|
|
|
|
/// \brief Diagnose any semantic errors with value-initialization of
|
|
|
|
/// the given type.
|
|
|
|
///
|
|
|
|
/// Value-initialization effectively zero-initializes any types
|
|
|
|
/// without user-declared constructors, and calls the default
|
|
|
|
/// constructor for a for any type that has a user-declared
|
|
|
|
/// constructor (C++ [dcl.init]p5). Value-initialization can fail when
|
|
|
|
/// a type with a user-declared constructor does not have an
|
|
|
|
/// accessible, non-deleted default constructor. In C, everything can
|
|
|
|
/// be value-initialized, which corresponds to C's notion of
|
|
|
|
/// initializing objects with static storage duration when no
|
2009-09-09 23:08:12 +08:00
|
|
|
/// initializer is provided for that object.
|
2009-02-03 01:43:21 +08:00
|
|
|
///
|
|
|
|
/// \returns true if there was an error, false otherwise.
|
|
|
|
bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) {
|
|
|
|
// C++ [dcl.init]p5:
|
|
|
|
//
|
|
|
|
// To value-initialize an object of type T means:
|
|
|
|
|
|
|
|
// -- if T is an array type, then each element is value-initialized;
|
|
|
|
if (const ArrayType *AT = Context.getAsArrayType(Type))
|
|
|
|
return CheckValueInitialization(AT->getElementType(), Loc);
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const RecordType *RT = Type->getAs<RecordType>()) {
|
2009-02-28 09:32:25 +08:00
|
|
|
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
|
2009-02-03 01:43:21 +08:00
|
|
|
// -- if T is a class type (clause 9) with a user-declared
|
|
|
|
// constructor (12.1), then the default constructor for T is
|
|
|
|
// called (and the initialization is ill-formed if T has no
|
|
|
|
// accessible default constructor);
|
2009-09-10 07:08:42 +08:00
|
|
|
if (ClassDecl->hasUserDeclaredConstructor()) {
|
|
|
|
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
|
|
|
|
|
|
|
|
CXXConstructorDecl *Constructor
|
|
|
|
= PerformInitializationByConstructor(Type,
|
|
|
|
MultiExprArg(*this, 0, 0),
|
|
|
|
Loc, SourceRange(Loc),
|
|
|
|
DeclarationName(),
|
|
|
|
IK_Direct,
|
|
|
|
ConstructorArgs);
|
|
|
|
if (!Constructor)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
OwningExprResult Init
|
|
|
|
= BuildCXXConstructExpr(Loc, Type, Constructor,
|
|
|
|
move_arg(ConstructorArgs));
|
|
|
|
if (Init.isInvalid())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// FIXME: Actually perform the value-initialization!
|
|
|
|
return false;
|
|
|
|
}
|
2009-02-03 01:43:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Type->isReferenceType()) {
|
|
|
|
// C++ [dcl.init]p5:
|
|
|
|
// [...] A program that calls for default-initialization or
|
|
|
|
// value-initialization of an entity of reference type is
|
|
|
|
// ill-formed. [...]
|
2009-05-16 15:39:55 +08:00
|
|
|
// FIXME: Once we have code that goes through this path, add an actual
|
|
|
|
// diagnostic :)
|
2009-02-03 01:43:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|