aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2011-10-20 21:14:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2011-10-20 21:14:49 +0000
commit36981b17ed939300f6f8fc2355a255f711fcef71 (patch)
treeee2483e98b09cac943dc93a6969d83ca737ff139 /lib/Sema/SemaInit.cpp
parent180abc3db9ae3b4fc63cd65b15697e6ffcc8a657 (diff)
downloadsrc-36981b17ed939300f6f8fc2355a255f711fcef71.tar.gz
src-36981b17ed939300f6f8fc2355a255f711fcef71.zip
Vendor import of clang release_30 branch r142614:vendor/clang/clang-r142614
Notes
Notes: svn path=/vendor/clang/dist/; revision=226586 svn path=/vendor/clang/clang-r142614/; revision=226587; tag=vendor/clang/clang-r142614
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r--lib/Sema/SemaInit.cpp1022
1 files changed, 730 insertions, 292 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 9fbcbab0b7d0..7ed3fa84c8d5 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -7,9 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements semantic analysis for initializers. The main entry
-// point is Sema::CheckInitList(), but all of the work is performed
-// within the InitListChecker class.
+// This file implements semantic analysis for initializers.
//
//===----------------------------------------------------------------------===//
@@ -24,6 +22,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
#include <map>
using namespace clang;
@@ -48,20 +47,30 @@ static Expr *IsStringInit(Expr *Init, const ArrayType *AT,
if (SL == 0) return 0;
QualType ElemTy = Context.getCanonicalType(AT->getElementType());
- // char array can be initialized with a narrow string.
- // Only allow char x[] = "foo"; not char x[] = L"foo";
- if (!SL->isWide())
+
+ switch (SL->getKind()) {
+ case StringLiteral::Ascii:
+ case StringLiteral::UTF8:
+ // char array can be initialized with a narrow string.
+ // Only allow char x[] = "foo"; not char x[] = L"foo";
return ElemTy->isCharType() ? Init : 0;
+ case StringLiteral::UTF16:
+ return ElemTy->isChar16Type() ? Init : 0;
+ case StringLiteral::UTF32:
+ return ElemTy->isChar32Type() ? Init : 0;
+ case StringLiteral::Wide:
+ // 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()))
+ return Init;
- // 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()))
- return Init;
+ return 0;
+ }
- return 0;
+ llvm_unreachable("missed a StringLiteral kind?");
}
static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) {
@@ -160,14 +169,14 @@ namespace {
class InitListChecker {
Sema &SemaRef;
bool hadError;
+ bool VerifyOnly; // no diagnostics, no structure building
std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic;
InitListExpr *FullyStructuredList;
void CheckImplicitInitList(const InitializedEntity &Entity,
InitListExpr *ParentIList, QualType T,
unsigned &Index, InitListExpr *StructuredList,
- unsigned &StructuredIndex,
- bool TopLevelObject = false);
+ unsigned &StructuredIndex);
void CheckExplicitInitList(const InitializedEntity &Entity,
InitListExpr *IList, QualType &T,
unsigned &Index, InitListExpr *StructuredList,
@@ -185,6 +194,11 @@ class InitListChecker {
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex);
+ void CheckComplexType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex);
void CheckScalarType(const InitializedEntity &Entity,
InitListExpr *IList, QualType DeclType,
unsigned &Index,
@@ -239,9 +253,12 @@ class InitListChecker {
InitListExpr *ILE, bool &RequiresSecondPass);
void FillInValueInitializations(const InitializedEntity &Entity,
InitListExpr *ILE, bool &RequiresSecondPass);
+ bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
+ Expr *InitExpr, FieldDecl *Field,
+ bool TopLevelObject);
public:
InitListChecker(Sema &S, const InitializedEntity &Entity,
- InitListExpr *IL, QualType &T);
+ InitListExpr *IL, QualType &T, bool VerifyOnly);
bool HadError() { return hadError; }
// @brief Retrieves the fully-structured initializer list used for
@@ -434,8 +451,9 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
- InitListExpr *IL, QualType &T)
- : SemaRef(S) {
+ InitListExpr *IL, QualType &T,
+ bool VerifyOnly)
+ : SemaRef(S), VerifyOnly(VerifyOnly) {
hadError = false;
unsigned newIndex = 0;
@@ -446,7 +464,7 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
FullyStructuredList, newStructuredIndex,
/*TopLevelObject=*/true);
- if (!hadError) {
+ if (!hadError && !VerifyOnly) {
bool RequiresSecondPass = false;
FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
if (RequiresSecondPass && !hadError)
@@ -472,7 +490,7 @@ int InitListChecker::numStructUnionElements(QualType DeclType) {
Field = structDecl->field_begin(),
FieldEnd = structDecl->field_end();
Field != FieldEnd; ++Field) {
- if ((*Field)->getIdentifier() || !(*Field)->isBitField())
+ if (!Field->isUnnamedBitfield())
++InitializableMembers;
}
if (structDecl->isUnion())
@@ -484,8 +502,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
InitListExpr *ParentIList,
QualType T, unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex,
- bool TopLevelObject) {
+ unsigned &StructuredIndex) {
int maxElements = 0;
if (T->isArrayType())
@@ -495,11 +512,12 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
else if (T->isVectorType())
maxElements = T->getAs<VectorType>()->getNumElements();
else
- assert(0 && "CheckImplicitInitList(): Illegal type");
+ llvm_unreachable("CheckImplicitInitList(): Illegal type");
if (maxElements == 0) {
- SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
- diag::err_implicit_empty_initializer);
+ if (!VerifyOnly)
+ SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(),
+ diag::err_implicit_empty_initializer);
++Index;
hadError = true;
return;
@@ -518,29 +536,31 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
CheckListElementTypes(Entity, ParentIList, T,
/*SubobjectIsDesignatorContext=*/false, Index,
StructuredSubobjectInitList,
- StructuredSubobjectInitIndex,
- TopLevelObject);
+ StructuredSubobjectInitIndex);
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
- StructuredSubobjectInitList->setType(T);
-
- // Update the structured sub-object initializer so that it's ending
- // range corresponds with the end of the last initializer it used.
- if (EndIndex < ParentIList->getNumInits()) {
- SourceLocation EndLoc
- = ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
- StructuredSubobjectInitList->setRBraceLoc(EndLoc);
- }
-
- // Warn about missing braces.
- if (T->isArrayType() || T->isRecordType()) {
- SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
- diag::warn_missing_braces)
- << StructuredSubobjectInitList->getSourceRange()
- << FixItHint::CreateInsertion(StructuredSubobjectInitList->getLocStart(),
- "{")
- << FixItHint::CreateInsertion(SemaRef.PP.getLocForEndOfToken(
+ if (!VerifyOnly) {
+ StructuredSubobjectInitList->setType(T);
+
+ // Update the structured sub-object initializer so that it's ending
+ // range corresponds with the end of the last initializer it used.
+ if (EndIndex < ParentIList->getNumInits()) {
+ SourceLocation EndLoc
+ = ParentIList->getInit(EndIndex)->getSourceRange().getEnd();
+ StructuredSubobjectInitList->setRBraceLoc(EndLoc);
+ }
+
+ // Warn about missing braces.
+ if (T->isArrayType() || T->isRecordType()) {
+ SemaRef.Diag(StructuredSubobjectInitList->getLocStart(),
+ diag::warn_missing_braces)
+ << StructuredSubobjectInitList->getSourceRange()
+ << FixItHint::CreateInsertion(
+ StructuredSubobjectInitList->getLocStart(), "{")
+ << FixItHint::CreateInsertion(
+ SemaRef.PP.getLocForEndOfToken(
StructuredSubobjectInitList->getLocEnd()),
- "}");
+ "}");
+ }
}
}
@@ -551,18 +571,31 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
unsigned &StructuredIndex,
bool TopLevelObject) {
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
- SyntacticToSemantic[IList] = StructuredList;
- StructuredList->setSyntacticForm(IList);
+ if (!VerifyOnly) {
+ SyntacticToSemantic[IList] = StructuredList;
+ StructuredList->setSyntacticForm(IList);
+ }
CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
Index, StructuredList, StructuredIndex, TopLevelObject);
- QualType ExprTy = T.getNonLValueExprType(SemaRef.Context);
- IList->setType(ExprTy);
- StructuredList->setType(ExprTy);
+ if (!VerifyOnly) {
+ QualType ExprTy = T.getNonLValueExprType(SemaRef.Context);
+ IList->setType(ExprTy);
+ StructuredList->setType(ExprTy);
+ }
if (hadError)
return;
if (Index < IList->getNumInits()) {
// We have leftover initializers
+ if (VerifyOnly) {
+ if (SemaRef.getLangOptions().CPlusPlus ||
+ (SemaRef.getLangOptions().OpenCL &&
+ IList->getType()->isVectorType())) {
+ hadError = true;
+ }
+ return;
+ }
+
if (StructuredIndex == 1 &&
IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) {
unsigned DK = diag::warn_excess_initializers_in_char_array_initializer;
@@ -599,7 +632,8 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
}
}
- if (T->isScalarType() && !TopLevelObject)
+ if (!VerifyOnly && T->isScalarType() && IList->getNumInits() == 1 &&
+ !TopLevelObject)
SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init)
<< IList->getSourceRange()
<< FixItHint::CreateRemoval(IList->getLocStart())
@@ -614,7 +648,12 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
bool TopLevelObject) {
- if (DeclType->isScalarType()) {
+ if (DeclType->isAnyComplexType() && SubobjectIsDesignatorContext) {
+ // Explicitly braced initializer for complex type can be real+imaginary
+ // parts.
+ CheckComplexType(Entity, IList, DeclType, Index,
+ StructuredList, StructuredIndex);
+ } else if (DeclType->isScalarType()) {
CheckScalarType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
} else if (DeclType->isVectorType()) {
@@ -635,12 +674,13 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
SubobjectIsDesignatorContext, Index,
StructuredList, StructuredIndex);
} else
- assert(0 && "Aggregate that isn't a structure or array?!");
+ llvm_unreachable("Aggregate that isn't a structure or array?!");
} else if (DeclType->isVoidType() || DeclType->isFunctionType()) {
// This type is invalid, issue a diagnostic.
++Index;
- SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
- << DeclType;
+ if (!VerifyOnly)
+ SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
+ << DeclType;
hadError = true;
} else if (DeclType->isRecordType()) {
// C++ [dcl.init]p14:
@@ -651,19 +691,22 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
// we have an initializer list and a destination type that is not
// an aggregate.
// FIXME: In C++0x, this is yet another form of initialization.
- SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
- << DeclType << IList->getSourceRange();
+ if (!VerifyOnly)
+ SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
+ << DeclType << IList->getSourceRange();
hadError = true;
} else if (DeclType->isReferenceType()) {
CheckReferenceType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
} else if (DeclType->isObjCObjectType()) {
- SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class)
- << DeclType;
+ if (!VerifyOnly)
+ SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class)
+ << DeclType;
hadError = true;
} else {
- SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
- << DeclType;
+ if (!VerifyOnly)
+ SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type)
+ << DeclType;
hadError = true;
}
}
@@ -701,8 +744,10 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// type here, though.
if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) {
- CheckStringInit(Str, ElemType, arrayType, SemaRef);
- UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ if (!VerifyOnly) {
+ CheckStringInit(Str, ElemType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ }
++Index;
return;
}
@@ -712,7 +757,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
} else if (SemaRef.getLangOptions().CPlusPlus) {
// C++ [dcl.init.aggr]p12:
// All implicit type conversions (clause 4) are considered when
- // initializing the aggregate member with an ini- tializer from
+ // initializing the aggregate member with an initializer from
// an initializer-list. If the initializer can initialize a
// member, the member is initialized. [...]
@@ -722,13 +767,15 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
if (Seq) {
- ExprResult Result =
- Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
- if (Result.isInvalid())
- hadError = true;
-
- UpdateStructuredListElement(StructuredList, StructuredIndex,
- Result.takeAs<Expr>());
+ if (!VerifyOnly) {
+ ExprResult Result =
+ Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
+ if (Result.isInvalid())
+ hadError = true;
+
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ Result.takeAs<Expr>());
+ }
++Index;
return;
}
@@ -745,7 +792,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// that of the expression.
ExprResult ExprRes = SemaRef.Owned(expr);
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
- SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes)
+ SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes,
+ !VerifyOnly)
== Sema::Compatible) {
if (ExprRes.isInvalid())
hadError = true;
@@ -775,25 +823,68 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
StructuredIndex);
++StructuredIndex;
} else {
- // We cannot initialize this element, so let
- // PerformCopyInitialization produce the appropriate diagnostic.
- SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
- SemaRef.Owned(expr));
+ if (!VerifyOnly) {
+ // We cannot initialize this element, so let
+ // PerformCopyInitialization produce the appropriate diagnostic.
+ SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
+ SemaRef.Owned(expr),
+ /*TopLevelOfInitList=*/true);
+ }
hadError = true;
++Index;
++StructuredIndex;
}
}
+void InitListChecker::CheckComplexType(const InitializedEntity &Entity,
+ InitListExpr *IList, QualType DeclType,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex) {
+ assert(Index == 0 && "Index in explicit init list must be zero");
+
+ // As an extension, clang supports complex initializers, which initialize
+ // a complex number component-wise. When an explicit initializer list for
+ // a complex number contains two two initializers, this extension kicks in:
+ // it exepcts the initializer list to contain two elements convertible to
+ // the element type of the complex type. The first element initializes
+ // the real part, and the second element intitializes the imaginary part.
+
+ if (IList->getNumInits() != 2)
+ return CheckScalarType(Entity, IList, DeclType, Index, StructuredList,
+ StructuredIndex);
+
+ // This is an extension in C. (The builtin _Complex type does not exist
+ // in the C++ standard.)
+ if (!SemaRef.getLangOptions().CPlusPlus && !VerifyOnly)
+ SemaRef.Diag(IList->getLocStart(), diag::ext_complex_component_init)
+ << IList->getSourceRange();
+
+ // Initialize the complex number.
+ QualType elementType = DeclType->getAs<ComplexType>()->getElementType();
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+ for (unsigned i = 0; i < 2; ++i) {
+ ElementEntity.setElementIndex(Index);
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
+ StructuredList, StructuredIndex);
+ }
+}
+
+
void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
InitListExpr *IList, QualType DeclType,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
if (Index >= IList->getNumInits()) {
- SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
- << IList->getSourceRange();
- hadError = true;
+ if (!SemaRef.getLangOptions().CPlusPlus0x) {
+ if (!VerifyOnly)
+ SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
+ << IList->getSourceRange();
+ hadError = true;
+ }
++Index;
++StructuredIndex;
return;
@@ -801,26 +892,36 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
Expr *expr = IList->getInit(Index);
if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
- SemaRef.Diag(SubIList->getLocStart(),
- diag::warn_many_braces_around_scalar_init)
- << SubIList->getSourceRange();
+ if (!VerifyOnly)
+ SemaRef.Diag(SubIList->getLocStart(),
+ diag::warn_many_braces_around_scalar_init)
+ << SubIList->getSourceRange();
CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
StructuredIndex);
return;
} else if (isa<DesignatedInitExpr>(expr)) {
- SemaRef.Diag(expr->getSourceRange().getBegin(),
- diag::err_designator_for_scalar_init)
- << DeclType << expr->getSourceRange();
+ if (!VerifyOnly)
+ SemaRef.Diag(expr->getSourceRange().getBegin(),
+ diag::err_designator_for_scalar_init)
+ << DeclType << expr->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
return;
}
+ if (VerifyOnly) {
+ if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
+ hadError = true;
+ ++Index;
+ return;
+ }
+
ExprResult Result =
SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
- SemaRef.Owned(expr));
+ SemaRef.Owned(expr),
+ /*TopLevelOfInitList=*/true);
Expr *ResultExpr = 0;
@@ -846,46 +947,57 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
- if (Index < IList->getNumInits()) {
- Expr *expr = IList->getInit(Index);
- if (isa<InitListExpr>(expr)) {
- SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
- << DeclType << IList->getSourceRange();
- hadError = true;
- ++Index;
- ++StructuredIndex;
- return;
- }
-
- ExprResult Result =
- SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
- SemaRef.Owned(expr));
-
- if (Result.isInvalid())
- hadError = true;
-
- expr = Result.takeAs<Expr>();
- IList->setInit(Index, expr);
-
- if (hadError)
- ++StructuredIndex;
- else
- UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
- ++Index;
- } else {
+ if (Index >= IList->getNumInits()) {
// FIXME: It would be wonderful if we could point at the actual member. In
// general, it would be useful to pass location information down the stack,
// so that we know the location (or decl) of the "current object" being
// initialized.
- SemaRef.Diag(IList->getLocStart(),
- diag::err_init_reference_member_uninitialized)
- << DeclType
- << IList->getSourceRange();
+ if (!VerifyOnly)
+ SemaRef.Diag(IList->getLocStart(),
+ diag::err_init_reference_member_uninitialized)
+ << DeclType
+ << IList->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
return;
}
+
+ Expr *expr = IList->getInit(Index);
+ if (isa<InitListExpr>(expr)) {
+ // FIXME: Allowed in C++11.
+ if (!VerifyOnly)
+ SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list)
+ << DeclType << IList->getSourceRange();
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
+ return;
+ }
+
+ if (VerifyOnly) {
+ if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(expr)))
+ hadError = true;
+ ++Index;
+ return;
+ }
+
+ ExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+ SemaRef.Owned(expr),
+ /*TopLevelOfInitList=*/true);
+
+ if (Result.isInvalid())
+ hadError = true;
+
+ expr = Result.takeAs<Expr>();
+ IList->setInit(Index, expr);
+
+ if (hadError)
+ ++StructuredIndex;
+ else
+ UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
+ ++Index;
}
void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
@@ -906,9 +1018,17 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
// instead of breaking it apart (which is doomed to failure anyway).
Expr *Init = IList->getInit(Index);
if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) {
+ if (VerifyOnly) {
+ if (!SemaRef.CanPerformCopyInitialization(Entity, SemaRef.Owned(Init)))
+ hadError = true;
+ ++Index;
+ return;
+ }
+
ExprResult Result =
SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(),
- SemaRef.Owned(Init));
+ SemaRef.Owned(Init),
+ /*TopLevelOfInitList=*/true);
Expr *ResultExpr = 0;
if (Result.isInvalid())
@@ -924,7 +1044,8 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
if (hadError)
++StructuredIndex;
else
- UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
+ ResultExpr);
++Index;
return;
}
@@ -977,11 +1098,11 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
}
// OpenCL requires all elements to be initialized.
- if (numEltsInit != maxElements)
- if (SemaRef.getLangOptions().OpenCL)
- SemaRef.Diag(IList->getSourceRange().getBegin(),
- diag::err_vector_incorrect_num_initializers)
- << (numEltsInit < maxElements) << maxElements << numEltsInit;
+ // FIXME: Shouldn't this set hadError to true then?
+ if (numEltsInit != maxElements && !VerifyOnly)
+ SemaRef.Diag(IList->getSourceRange().getBegin(),
+ diag::err_vector_incorrect_num_initializers)
+ << (numEltsInit < maxElements) << maxElements << numEltsInit;
}
void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
@@ -997,14 +1118,16 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
if (Index < IList->getNumInits()) {
if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType,
SemaRef.Context)) {
- CheckStringInit(Str, DeclType, arrayType, SemaRef);
// We place the string literal directly into the resulting
// initializer list. This is the only place where the structure
// of the structured initializer list doesn't match exactly,
// because doing so would involve allocating one character
// constant for each string.
- UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
- StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
+ if (!VerifyOnly) {
+ CheckStringInit(Str, DeclType, arrayType, SemaRef);
+ UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
+ StructuredList->resizeInits(SemaRef.Context, StructuredIndex);
+ }
++Index;
return;
}
@@ -1013,9 +1136,10 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
// Check for VLAs; in standard C it would be possible to check this
// earlier, but I don't know where clang accepts VLAs (gcc accepts
// them in all sorts of strange places).
- SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
- diag::err_variable_object_no_init)
- << VAT->getSizeExpr()->getSourceRange();
+ if (!VerifyOnly)
+ SemaRef.Diag(VAT->getSizeExpr()->getLocStart(),
+ diag::err_variable_object_no_init)
+ << VAT->getSizeExpr()->getSourceRange();
hadError = true;
++Index;
++StructuredIndex;
@@ -1085,7 +1209,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
if (!maxElementsKnown && elementIndex > maxElements)
maxElements = elementIndex;
}
- if (!hadError && DeclType->isIncompleteArrayType()) {
+ if (!hadError && DeclType->isIncompleteArrayType() && !VerifyOnly) {
// If this is an incomplete array type, the actual type needs to
// be calculated here.
llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned());
@@ -1101,6 +1225,45 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
}
}
+bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
+ Expr *InitExpr,
+ FieldDecl *Field,
+ bool TopLevelObject) {
+ // Handle GNU flexible array initializers.
+ unsigned FlexArrayDiag;
+ if (isa<InitListExpr>(InitExpr) &&
+ cast<InitListExpr>(InitExpr)->getNumInits() == 0) {
+ // Empty flexible array init always allowed as an extension
+ FlexArrayDiag = diag::ext_flexible_array_init;
+ } else if (SemaRef.getLangOptions().CPlusPlus) {
+ // Disallow flexible array init in C++; it is not required for gcc
+ // compatibility, and it needs work to IRGen correctly in general.
+ FlexArrayDiag = diag::err_flexible_array_init;
+ } else if (!TopLevelObject) {
+ // Disallow flexible array init on non-top-level object
+ FlexArrayDiag = diag::err_flexible_array_init;
+ } else if (Entity.getKind() != InitializedEntity::EK_Variable) {
+ // Disallow flexible array init on anything which is not a variable.
+ FlexArrayDiag = diag::err_flexible_array_init;
+ } else if (cast<VarDecl>(Entity.getDecl())->hasLocalStorage()) {
+ // Disallow flexible array init on local variables.
+ FlexArrayDiag = diag::err_flexible_array_init;
+ } else {
+ // Allow other cases.
+ FlexArrayDiag = diag::ext_flexible_array_init;
+ }
+
+ if (!VerifyOnly) {
+ SemaRef.Diag(InitExpr->getSourceRange().getBegin(),
+ FlexArrayDiag)
+ << InitExpr->getSourceRange().getBegin();
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << Field;
+ }
+
+ return FlexArrayDiag != diag::ext_flexible_array_init;
+}
+
void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
InitListExpr *IList,
QualType DeclType,
@@ -1120,13 +1283,15 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
if (DeclType->isUnionType() && IList->getNumInits() == 0) {
- // Value-initialize the first named member of the union.
- RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
- for (RecordDecl::field_iterator FieldEnd = RD->field_end();
- Field != FieldEnd; ++Field) {
- if (Field->getDeclName()) {
- StructuredList->setInitializedFieldInUnion(*Field);
- break;
+ if (!VerifyOnly) {
+ // Value-initialize the first named member of the union.
+ RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl();
+ for (RecordDecl::field_iterator FieldEnd = RD->field_end();
+ Field != FieldEnd; ++Field) {
+ if (Field->getDeclName()) {
+ StructuredList->setInitializedFieldInUnion(*Field);
+ break;
+ }
}
}
return;
@@ -1186,13 +1351,18 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
// Make sure we can use this declaration.
- if (SemaRef.DiagnoseUseOfDecl(*Field,
- IList->getInit(Index)->getLocStart())) {
+ bool InvalidUse;
+ if (VerifyOnly)
+ InvalidUse = !SemaRef.CanUseDecl(*Field);
+ else
+ InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field,
+ IList->getInit(Index)->getLocStart());
+ if (InvalidUse) {
++Index;
++Field;
hadError = true;
continue;
- }
+ }
InitializedEntity MemberEntity =
InitializedEntity::InitializeMember(*Field, &Entity);
@@ -1200,7 +1370,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
StructuredList, StructuredIndex);
InitializedSomething = true;
- if (DeclType->isUnionType()) {
+ if (DeclType->isUnionType() && !VerifyOnly) {
// Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field);
}
@@ -1209,8 +1379,9 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
// Emit warnings for missing struct field initializers.
- if (InitializedSomething && CheckForMissingFields && Field != FieldEnd &&
- !Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) {
+ if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
+ Field != FieldEnd && !Field->getType()->isIncompleteArrayType() &&
+ !DeclType->isUnionType()) {
// It is possible we have one or more unnamed bitfields remaining.
// Find first (if any) named field and emit warning.
for (RecordDecl::field_iterator it = Field, end = RD->field_end();
@@ -1227,24 +1398,11 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
Index >= IList->getNumInits())
return;
- // Handle GNU flexible array initializers.
- if (!TopLevelObject &&
- (!isa<InitListExpr>(IList->getInit(Index)) ||
- cast<InitListExpr>(IList->getInit(Index))->getNumInits() > 0)) {
- SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
- diag::err_flexible_array_init_nonempty)
- << IList->getInit(Index)->getSourceRange().getBegin();
- SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
- << *Field;
+ if (CheckFlexibleArrayInit(Entity, IList->getInit(Index), *Field,
+ TopLevelObject)) {
hadError = true;
++Index;
return;
- } else {
- SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
- diag::ext_flexible_array_init)
- << IList->getInit(Index)->getSourceRange().getBegin();
- SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
- << *Field;
}
InitializedEntity MemberEntity =
@@ -1269,7 +1427,7 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
typedef DesignatedInitExpr::Designator Designator;
// Build the replacement designators.
- llvm::SmallVector<Designator, 4> Replacements;
+ SmallVector<Designator, 4> Replacements;
for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
PE = IndirectField->chain_end(); PI != PE; ++PI) {
if (PI + 1 == PE)
@@ -1304,6 +1462,18 @@ static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
return 0;
}
+static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef,
+ DesignatedInitExpr *DIE) {
+ unsigned NumIndexExprs = DIE->getNumSubExprs() - 1;
+ SmallVector<Expr*, 4> IndexExprs(NumIndexExprs);
+ for (unsigned I = 0; I < NumIndexExprs; ++I)
+ IndexExprs[I] = DIE->getSubExpr(I + 1);
+ return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators_begin(),
+ DIE->size(), IndexExprs.data(),
+ NumIndexExprs, DIE->getEqualOrColonLoc(),
+ DIE->usesGNUSyntax(), DIE->getInit());
+}
+
/// @brief Check the well-formedness of a C99 designated initializer.
///
/// Determines whether the designated initializer @p DIE, which
@@ -1342,14 +1512,14 @@ static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
bool
InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
InitListExpr *IList,
- DesignatedInitExpr *DIE,
- unsigned DesigIdx,
- QualType &CurrentObjectType,
- RecordDecl::field_iterator *NextField,
- llvm::APSInt *NextElementIndex,
- unsigned &Index,
- InitListExpr *StructuredList,
- unsigned &StructuredIndex,
+ DesignatedInitExpr *DIE,
+ unsigned DesigIdx,
+ QualType &CurrentObjectType,
+ RecordDecl::field_iterator *NextField,
+ llvm::APSInt *NextElementIndex,
+ unsigned &Index,
+ InitListExpr *StructuredList,
+ unsigned &StructuredIndex,
bool FinishSubobjectInit,
bool TopLevelObject) {
if (DesigIdx == DIE->size()) {
@@ -1374,19 +1544,21 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
return hadError && !prevHadError;
}
- bool IsFirstDesignator = (DesigIdx == 0);
- assert((IsFirstDesignator || StructuredList) &&
- "Need a non-designated initializer list to start from");
-
DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx);
- // Determine the structural initializer list that corresponds to the
- // current subobject.
- StructuredList = IsFirstDesignator? SyntacticToSemantic[IList]
- : getStructuredSubobjectInit(IList, Index, CurrentObjectType,
- StructuredList, StructuredIndex,
- SourceRange(D->getStartLocation(),
- DIE->getSourceRange().getEnd()));
- assert(StructuredList && "Expected a structured initializer list");
+ bool IsFirstDesignator = (DesigIdx == 0);
+ if (!VerifyOnly) {
+ assert((IsFirstDesignator || StructuredList) &&
+ "Need a non-designated initializer list to start from");
+
+ // Determine the structural initializer list that corresponds to the
+ // current subobject.
+ StructuredList = IsFirstDesignator? SyntacticToSemantic[IList]
+ : getStructuredSubobjectInit(IList, Index, CurrentObjectType,
+ StructuredList, StructuredIndex,
+ SourceRange(D->getStartLocation(),
+ DIE->getSourceRange().getEnd()));
+ assert(StructuredList && "Expected a structured initializer list");
+ }
if (D->isFieldDesignator()) {
// C99 6.7.8p7:
@@ -1403,8 +1575,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
SourceLocation Loc = D->getDotLoc();
if (Loc.isInvalid())
Loc = D->getFieldLoc();
- SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
- << SemaRef.getLangOptions().CPlusPlus << CurrentObjectType;
+ if (!VerifyOnly)
+ SemaRef.Diag(Loc, diag::err_field_designator_non_aggr)
+ << SemaRef.getLangOptions().CPlusPlus << CurrentObjectType;
++Index;
return true;
}
@@ -1427,6 +1600,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (!KnownField && Field->isAnonymousStructOrUnion()) {
if (IndirectFieldDecl *IF =
FindIndirectFieldDesignator(*Field, FieldName)) {
+ // In verify mode, don't modify the original.
+ if (VerifyOnly)
+ DIE = CloneDesignatedInitExpr(SemaRef, DIE);
ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF);
D = DIE->getDesignator(DesigIdx);
break;
@@ -1441,6 +1617,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
}
if (Field == FieldEnd) {
+ if (VerifyOnly) {
+ ++Index;
+ return true; // No typo correction when just trying this out.
+ }
+
// 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),
@@ -1470,6 +1651,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
<< FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr);
SemaRef.Diag(ReplacementField->getLocation(),
diag::note_previous_decl) << CorrectedQuotedStr;
+ hadError = true;
} else {
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
<< FieldName << CurrentObjectType;
@@ -1510,22 +1692,30 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// the initializer list.
if (RT->getDecl()->isUnion()) {
FieldIndex = 0;
- StructuredList->setInitializedFieldInUnion(*Field);
+ if (!VerifyOnly)
+ StructuredList->setInitializedFieldInUnion(*Field);
}
// Make sure we can use this declaration.
- if (SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc())) {
+ bool InvalidUse;
+ if (VerifyOnly)
+ InvalidUse = !SemaRef.CanUseDecl(*Field);
+ else
+ InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc());
+ if (InvalidUse) {
++Index;
return true;
- }
+ }
- // Update the designator with the field declaration.
- D->setField(*Field);
+ if (!VerifyOnly) {
+ // Update the designator with the field declaration.
+ D->setField(*Field);
- // Make sure that our non-designated initializer list has space
- // for a subobject corresponding to this field.
- if (FieldIndex >= StructuredList->getNumInits())
- StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);
+ // Make sure that our non-designated initializer list has space
+ // for a subobject corresponding to this field.
+ if (FieldIndex >= StructuredList->getNumInits())
+ StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1);
+ }
// This designator names a flexible array member.
if (Field->getType()->isIncompleteArrayType()) {
@@ -1533,38 +1723,36 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if ((DesigIdx + 1) != DIE->size()) {
// We can't designate an object within the flexible array
// member (because GCC doesn't allow it).
- DesignatedInitExpr::Designator *NextD
- = DIE->getDesignator(DesigIdx + 1);
- SemaRef.Diag(NextD->getStartLocation(),
- diag::err_designator_into_flexible_array_member)
- << SourceRange(NextD->getStartLocation(),
- DIE->getSourceRange().getEnd());
- SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
- << *Field;
+ if (!VerifyOnly) {
+ DesignatedInitExpr::Designator *NextD
+ = DIE->getDesignator(DesigIdx + 1);
+ SemaRef.Diag(NextD->getStartLocation(),
+ diag::err_designator_into_flexible_array_member)
+ << SourceRange(NextD->getStartLocation(),
+ DIE->getSourceRange().getEnd());
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ }
Invalid = true;
}
if (!hadError && !isa<InitListExpr>(DIE->getInit()) &&
!isa<StringLiteral>(DIE->getInit())) {
// The initializer is not an initializer list.
- SemaRef.Diag(DIE->getInit()->getSourceRange().getBegin(),
- diag::err_flexible_array_init_needs_braces)
- << DIE->getInit()->getSourceRange();
- SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
- << *Field;
+ if (!VerifyOnly) {
+ SemaRef.Diag(DIE->getInit()->getSourceRange().getBegin(),
+ diag::err_flexible_array_init_needs_braces)
+ << DIE->getInit()->getSourceRange();
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ }
Invalid = true;
}
- // Handle GNU flexible array initializers.
- if (!Invalid && !TopLevelObject &&
- cast<InitListExpr>(DIE->getInit())->getNumInits() > 0) {
- SemaRef.Diag(DIE->getSourceRange().getBegin(),
- diag::err_flexible_array_init_nonempty)
- << DIE->getSourceRange().getBegin();
- SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
- << *Field;
+ // Check GNU flexible array initializer.
+ if (!Invalid && CheckFlexibleArrayInit(Entity, DIE->getInit(), *Field,
+ TopLevelObject))
Invalid = true;
- }
if (Invalid) {
++Index;
@@ -1651,8 +1839,9 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// [ constant-expression ... constant-expression ]
const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType);
if (!AT) {
- SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
- << CurrentObjectType;
+ if (!VerifyOnly)
+ SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array)
+ << CurrentObjectType;
++Index;
return true;
}
@@ -1661,15 +1850,15 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
if (D->isArrayDesignator()) {
IndexExpr = DIE->getArrayIndex(*D);
- DesignatedStartIndex = IndexExpr->EvaluateAsInt(SemaRef.Context);
+ DesignatedStartIndex = IndexExpr->EvaluateKnownConstInt(SemaRef.Context);
DesignatedEndIndex = DesignatedStartIndex;
} else {
assert(D->isArrayRangeDesignator() && "Need array-range designator");
DesignatedStartIndex =
- DIE->getArrayRangeStart(*D)->EvaluateAsInt(SemaRef.Context);
+ DIE->getArrayRangeStart(*D)->EvaluateKnownConstInt(SemaRef.Context);
DesignatedEndIndex =
- DIE->getArrayRangeEnd(*D)->EvaluateAsInt(SemaRef.Context);
+ DIE->getArrayRangeEnd(*D)->EvaluateKnownConstInt(SemaRef.Context);
IndexExpr = DIE->getArrayRangeEnd(*D);
// Codegen can't handle evaluating array range designators that have side
@@ -1678,7 +1867,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// elements with something that has a side effect, so codegen can emit an
// "error unsupported" error instead of miscompiling the app.
if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&&
- DIE->getInit()->HasSideEffects(SemaRef.Context))
+ DIE->getInit()->HasSideEffects(SemaRef.Context) && !VerifyOnly)
FullyStructuredList->sawArrayRangeDesignator();
}
@@ -1691,10 +1880,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
= DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
if (DesignatedEndIndex >= MaxElements) {
- SemaRef.Diag(IndexExpr->getSourceRange().getBegin(),
- diag::err_array_designator_too_large)
- << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
- << IndexExpr->getSourceRange();
+ if (!VerifyOnly)
+ SemaRef.Diag(IndexExpr->getSourceRange().getBegin(),
+ diag::err_array_designator_too_large)
+ << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
+ << IndexExpr->getSourceRange();
++Index;
return true;
}
@@ -1713,7 +1903,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Make sure that our non-designated initializer list has space
// for a subobject corresponding to this array element.
- if (DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
+ if (!VerifyOnly &&
+ DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
StructuredList->resizeInits(SemaRef.Context,
DesignatedEndIndex.getZExtValue() + 1);
@@ -1773,6 +1964,8 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
InitListExpr *StructuredList,
unsigned StructuredIndex,
SourceRange InitRange) {
+ if (VerifyOnly)
+ return 0; // No structured list in verification-only mode.
Expr *ExistingInit = 0;
if (!StructuredList)
ExistingInit = SyntacticToSemantic[IList];
@@ -1844,9 +2037,6 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
RDecl->field_end());
}
- if (NumElements < NumInits)
- NumElements = IList->getNumInits();
-
Result->reserveInits(SemaRef.Context, NumElements);
// Link this new initializer list into the structured initializer
@@ -1915,8 +2105,8 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
typedef DesignatedInitExpr::Designator ASTDesignator;
bool Invalid = false;
- llvm::SmallVector<ASTDesignator, 32> Designators;
- llvm::SmallVector<Expr *, 32> InitExpressions;
+ SmallVector<ASTDesignator, 32> Designators;
+ SmallVector<Expr *, 32> InitExpressions;
// Build designators and check array designator expressions.
for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) {
@@ -2007,15 +2197,6 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
return Owned(DIE);
}
-bool Sema::CheckInitList(const InitializedEntity &Entity,
- InitListExpr *&InitList, QualType &DeclType) {
- InitListChecker CheckInitList(*this, Entity, InitList, DeclType);
- if (!CheckInitList.HadError())
- InitList = CheckInitList.getFullyStructuredList();
-
- return CheckInitList.HadError();
-}
-
//===----------------------------------------------------------------------===//
// Initialization entity
//===----------------------------------------------------------------------===//
@@ -2027,9 +2208,14 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) {
Kind = EK_ArrayElement;
Type = AT->getElementType();
- } else {
+ } else if (const VectorType *VT = Parent.getType()->getAs<VectorType>()) {
Kind = EK_VectorElement;
- Type = Parent.getType()->getAs<VectorType>()->getElementType();
+ Type = VT->getElementType();
+ } else {
+ const ComplexType *CT = Parent.getType()->getAs<ComplexType>();
+ assert(CT && "Unexpected type");
+ Kind = EK_ComplexElement;
+ Type = CT->getElementType();
}
}
@@ -2066,6 +2252,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_Delegating:
case EK_ArrayElement:
case EK_VectorElement:
+ case EK_ComplexElement:
case EK_BlockElement:
return DeclarationName();
}
@@ -2091,6 +2278,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const {
case EK_Delegating:
case EK_ArrayElement:
case EK_VectorElement:
+ case EK_ComplexElement:
case EK_BlockElement:
return 0;
}
@@ -2114,6 +2302,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Delegating:
case EK_ArrayElement:
case EK_VectorElement:
+ case EK_ComplexElement:
case EK_BlockElement:
break;
}
@@ -2139,6 +2328,7 @@ void InitializationSequence::Step::Destroy() {
case SK_QualificationConversionXValue:
case SK_QualificationConversionLValue:
case SK_ListInitialization:
+ case SK_ListConstructorCall:
case SK_ConstructorInitialization:
case SK_ZeroInitialization:
case SK_CAssignment:
@@ -2182,6 +2372,7 @@ bool InitializationSequence::isAmbiguous() const {
case FK_Incomplete:
case FK_ArrayTypeMismatch:
case FK_NonConstantArrayInit:
+ case FK_ListInitializationFailed:
return false;
case FK_ReferenceInitOverloadFailed:
@@ -2197,12 +2388,171 @@ bool InitializationSequence::isConstructorInitialization() const {
return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization;
}
+bool InitializationSequence::endsWithNarrowing(ASTContext &Ctx,
+ const Expr *Initializer,
+ bool *isInitializerConstant,
+ APValue *ConstantValue) const {
+ if (Steps.empty() || Initializer->isValueDependent())
+ return false;
+
+ const Step &LastStep = Steps.back();
+ if (LastStep.Kind != SK_ConversionSequence)
+ return false;
+
+ const ImplicitConversionSequence &ICS = *LastStep.ICS;
+ const StandardConversionSequence *SCS = NULL;
+ switch (ICS.getKind()) {
+ case ImplicitConversionSequence::StandardConversion:
+ SCS = &ICS.Standard;
+ break;
+ case ImplicitConversionSequence::UserDefinedConversion:
+ SCS = &ICS.UserDefined.After;
+ break;
+ case ImplicitConversionSequence::AmbiguousConversion:
+ case ImplicitConversionSequence::EllipsisConversion:
+ case ImplicitConversionSequence::BadConversion:
+ return false;
+ }
+
+ // Check if SCS represents a narrowing conversion, according to C++0x
+ // [dcl.init.list]p7:
+ //
+ // A narrowing conversion is an implicit conversion ...
+ ImplicitConversionKind PossibleNarrowing = SCS->Second;
+ QualType FromType = SCS->getToType(0);
+ QualType ToType = SCS->getToType(1);
+ switch (PossibleNarrowing) {
+ // * from a floating-point type to an integer type, or
+ //
+ // * from an integer type or unscoped enumeration type to a floating-point
+ // type, except where the source is a constant expression and the actual
+ // value after conversion will fit into the target type and will produce
+ // the original value when converted back to the original type, or
+ case ICK_Floating_Integral:
+ if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
+ *isInitializerConstant = false;
+ return true;
+ } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
+ llvm::APSInt IntConstantValue;
+ if (Initializer &&
+ Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) {
+ // Convert the integer to the floating type.
+ llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
+ Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(),
+ llvm::APFloat::rmNearestTiesToEven);
+ // And back.
+ llvm::APSInt ConvertedValue = IntConstantValue;
+ bool ignored;
+ Result.convertToInteger(ConvertedValue,
+ llvm::APFloat::rmTowardZero, &ignored);
+ // If the resulting value is different, this was a narrowing conversion.
+ if (IntConstantValue != ConvertedValue) {
+ *isInitializerConstant = true;
+ *ConstantValue = APValue(IntConstantValue);
+ return true;
+ }
+ } else {
+ // Variables are always narrowings.
+ *isInitializerConstant = false;
+ return true;
+ }
+ }
+ return false;
+
+ // * from long double to double or float, or from double to float, except
+ // where the source is a constant expression and the actual value after
+ // conversion is within the range of values that can be represented (even
+ // if it cannot be represented exactly), or
+ case ICK_Floating_Conversion:
+ if (1 == Ctx.getFloatingTypeOrder(FromType, ToType)) {
+ // FromType is larger than ToType.
+ Expr::EvalResult InitializerValue;
+ // FIXME: Check whether Initializer is a constant expression according
+ // to C++0x [expr.const], rather than just whether it can be folded.
+ if (Initializer->Evaluate(InitializerValue, Ctx) &&
+ !InitializerValue.HasSideEffects && InitializerValue.Val.isFloat()) {
+ // Constant! (Except for FIXME above.)
+ llvm::APFloat FloatVal = InitializerValue.Val.getFloat();
+ // Convert the source value into the target type.
+ bool ignored;
+ llvm::APFloat::opStatus ConvertStatus = FloatVal.convert(
+ Ctx.getFloatTypeSemantics(ToType),
+ llvm::APFloat::rmNearestTiesToEven, &ignored);
+ // If there was no overflow, the source value is within the range of
+ // values that can be represented.
+ if (ConvertStatus & llvm::APFloat::opOverflow) {
+ *isInitializerConstant = true;
+ *ConstantValue = InitializerValue.Val;
+ return true;
+ }
+ } else {
+ *isInitializerConstant = false;
+ return true;
+ }
+ }
+ return false;
+
+ // * from an integer type or unscoped enumeration type to an integer type
+ // that cannot represent all the values of the original type, except where
+ // the source is a constant expression and the actual value after
+ // conversion will fit into the target type and will produce the original
+ // value when converted back to the original type.
+ case ICK_Boolean_Conversion: // Bools are integers too.
+ if (!FromType->isIntegralOrUnscopedEnumerationType()) {
+ // Boolean conversions can be from pointers and pointers to members
+ // [conv.bool], and those aren't considered narrowing conversions.
+ return false;
+ } // Otherwise, fall through to the integral case.
+ case ICK_Integral_Conversion: {
+ assert(FromType->isIntegralOrUnscopedEnumerationType());
+ assert(ToType->isIntegralOrUnscopedEnumerationType());
+ const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
+ const unsigned FromWidth = Ctx.getIntWidth(FromType);
+ const bool ToSigned = ToType->isSignedIntegerOrEnumerationType();
+ const unsigned ToWidth = Ctx.getIntWidth(ToType);
+
+ if (FromWidth > ToWidth ||
+ (FromWidth == ToWidth && FromSigned != ToSigned)) {
+ // Not all values of FromType can be represented in ToType.
+ llvm::APSInt InitializerValue;
+ if (Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) {
+ *isInitializerConstant = true;
+ *ConstantValue = APValue(InitializerValue);
+
+ // Add a bit to the InitializerValue so we don't have to worry about
+ // signed vs. unsigned comparisons.
+ InitializerValue = InitializerValue.extend(
+ InitializerValue.getBitWidth() + 1);
+ // Convert the initializer to and from the target width and signed-ness.
+ llvm::APSInt ConvertedValue = InitializerValue;
+ ConvertedValue = ConvertedValue.trunc(ToWidth);
+ ConvertedValue.setIsSigned(ToSigned);
+ ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth());
+ ConvertedValue.setIsSigned(InitializerValue.isSigned());
+ // If the result is different, this was a narrowing conversion.
+ return ConvertedValue != InitializerValue;
+ } else {
+ // Variables are always narrowings.
+ *isInitializerConstant = false;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ default:
+ // Other kinds of conversions are not narrowings.
+ return false;
+ }
+}
+
void InitializationSequence::AddAddressOverloadResolutionStep(
FunctionDecl *Function,
DeclAccessPair Found) {
Step S;
S.Kind = SK_ResolveAddressOfOverloadedFunction;
S.Type = Function->getType();
+ S.Function.HadMultipleCandidates = false;
S.Function.Function = Function;
S.Function.FoundDecl = Found;
Steps.push_back(S);
@@ -2242,6 +2592,7 @@ void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
Step S;
S.Kind = SK_UserConversion;
S.Type = T;
+ S.Function.HadMultipleCandidates = false;
S.Function.Function = Function;
S.Function.FoundDecl = FoundDecl;
Steps.push_back(S);
@@ -2291,6 +2642,7 @@ InitializationSequence::AddConstructorInitializationStep(
Step S;
S.Kind = SK_ConstructorInitialization;
S.Type = T;
+ S.Function.HadMultipleCandidates = false;
S.Function.Function = Constructor;
S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access);
Steps.push_back(S);
@@ -2391,44 +2743,33 @@ static void TryListInitialization(Sema &S,
const InitializationKind &Kind,
InitListExpr *InitList,
InitializationSequence &Sequence) {
- // FIXME: We only perform rudimentary checking of list
- // initializations at this point, then assume that any list
- // initialization of an array, aggregate, or scalar will be
- // well-formed. When we actually "perform" list initialization, we'll
- // do all of the necessary checking. C++0x initializer lists will
- // force us to perform more checking here.
-
QualType DestType = Entity.getType();
- // C++ [dcl.init]p13:
- // If T is a scalar type, then a declaration of the form
- //
- // T x = { a };
- //
- // is equivalent to
- //
- // T x = a;
- if (DestType->isScalarType()) {
- if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) {
- Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
- return;
- }
-
- // Assume scalar initialization from a single value works.
- } else if (DestType->isAggregateType()) {
- // Assume aggregate initialization works.
- } else if (DestType->isVectorType()) {
- // Assume vector initialization works.
- } else if (DestType->isReferenceType()) {
- // FIXME: C++0x defines behavior for this.
+ // C++ doesn't allow scalar initialization with more than one argument.
+ // But C99 complex numbers are scalars and it makes sense there.
+ if (S.getLangOptions().CPlusPlus && DestType->isScalarType() &&
+ !DestType->isAnyComplexType() && InitList->getNumInits() > 1) {
+ Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
+ return;
+ }
+ // FIXME: C++0x defines behavior for these two cases.
+ if (DestType->isReferenceType()) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
return;
- } else if (DestType->isRecordType()) {
- // FIXME: C++0x defines behavior for this
+ }
+ if (DestType->isRecordType() && !DestType->isAggregateType()) {
Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+ return;
}
- // Add a general "list initialization" step.
+ InitListChecker CheckInitList(S, Entity, InitList,
+ DestType, /*VerifyOnly=*/true);
+ if (CheckInitList.HadError()) {
+ Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
+ return;
+ }
+
+ // Add the list initialization step with the built init list.
Sequence.AddListInitializationStep(DestType);
}
@@ -2767,7 +3108,7 @@ static void TryReferenceInitialization(Sema &S,
//
// The constructor that would be used to make the copy shall
// be callable whether or not the copy is actually done.
- if (!S.getLangOptions().CPlusPlus0x && !S.getLangOptions().Microsoft)
+ if (!S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt)
Sequence.AddExtraneousCopyToTemporary(cv2T2);
}
@@ -2887,6 +3228,14 @@ static void TryConstructorInitialization(Sema &S,
Expr **Args, unsigned NumArgs,
QualType DestType,
InitializationSequence &Sequence) {
+ // Check constructor arguments for self reference.
+ if (DeclaratorDecl *DD = Entity.getDecl())
+ // Parameters arguments are occassionially constructed with itself,
+ // for instance, in recursive functions. Skip them.
+ if (!isa<ParmVarDecl>(DD))
+ for (unsigned i = 0; i < NumArgs; ++i)
+ S.CheckSelfReference(DD, Args[i]);
+
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
@@ -3577,7 +3926,7 @@ InitializationSequence::InitializationSequence(Sema &S,
}
InitializationSequence::~InitializationSequence() {
- for (llvm::SmallVectorImpl<Step>::iterator Step = Steps.begin(),
+ for (SmallVectorImpl<Step>::iterator Step = Steps.begin(),
StepEnd = Steps.end();
Step != StepEnd; ++Step)
Step->Destroy();
@@ -3613,6 +3962,7 @@ getAssignmentAction(const InitializedEntity &Entity) {
case InitializedEntity::EK_Member:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_ComplexElement:
case InitializedEntity::EK_BlockElement:
return Sema::AA_Initializing;
}
@@ -3632,6 +3982,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_ComplexElement:
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_BlockElement:
return false;
@@ -3654,6 +4005,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_ComplexElement:
case InitializedEntity::EK_BlockElement:
return false;
@@ -3739,6 +4091,7 @@ static ExprResult CopyObject(Sema &S,
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
case InitializedEntity::EK_VectorElement:
+ case InitializedEntity::EK_ComplexElement:
case InitializedEntity::EK_BlockElement:
Loc = CurInitExpr->getLocStart();
break;
@@ -3790,6 +4143,8 @@ static ExprResult CopyObject(Sema &S,
&CurInitExpr, 1, CandidateSet, true);
}
+ bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, Loc, Best)) {
case OR_Success:
@@ -3867,6 +4222,7 @@ static ExprResult CopyObject(Sema &S,
// Actually perform the constructor call.
CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
move_arg(ConstructorArgs),
+ HadMultipleCandidates,
/*ZeroInit*/ false,
CXXConstructExpr::CK_Complete,
SourceRange());
@@ -3982,6 +4338,7 @@ InitializationSequence::Perform(Sema &S,
case SK_QualificationConversionXValue:
case SK_QualificationConversionRValue:
case SK_ConversionSequence:
+ case SK_ListConstructorCall:
case SK_ListInitialization:
case SK_CAssignment:
case SK_StringInit:
@@ -4127,8 +4484,8 @@ InitializationSequence::Perform(Sema &S,
bool IsCopy = false;
FunctionDecl *Fn = Step->Function.Function;
DeclAccessPair FoundFn = Step->Function.FoundDecl;
+ bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
bool CreatedObject = false;
- bool IsLvalue = false;
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
// Build a call to the selected constructor.
ASTOwningVector<Expr*> ConstructorArgs(S);
@@ -4146,6 +4503,7 @@ InitializationSequence::Perform(Sema &S,
// Build the an expression that constructs a temporary.
CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
move_arg(ConstructorArgs),
+ HadMultipleCandidates,
/*ZeroInit*/ false,
CXXConstructExpr::CK_Complete,
SourceRange());
@@ -4166,7 +4524,6 @@ InitializationSequence::Perform(Sema &S,
} else {
// Build a call to the conversion function.
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
- IsLvalue = Conversion->getResultType()->isLValueReferenceType();
S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0,
FoundFn);
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
@@ -4182,7 +4539,8 @@ InitializationSequence::Perform(Sema &S,
CurInit = move(CurInitExprRes);
// Build the actual call to the conversion function.
- CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion);
+ CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion,
+ HadMultipleCandidates);
if (CurInit.isInvalid() || !CurInit.get())
return ExprError();
@@ -4206,11 +4564,10 @@ InitializationSequence::Perform(Sema &S,
}
}
- // FIXME: xvalues
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
CurInit.get()->getType(),
CastKind, CurInit.get(), 0,
- IsLvalue ? VK_LValue : VK_RValue));
+ CurInit.get()->getValueKind()));
if (RequiresCopy)
CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
@@ -4251,18 +4608,24 @@ InitializationSequence::Perform(Sema &S,
case SK_ListInitialization: {
InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
QualType Ty = Step->Type;
- if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty))
+ InitListChecker PerformInitList(S, Entity, InitList,
+ ResultType ? *ResultType : Ty, /*VerifyOnly=*/false);
+ if (PerformInitList.HadError())
return ExprError();
CurInit.release();
- CurInit = S.Owned(InitList);
+ CurInit = S.Owned(PerformInitList.getFullyStructuredList());
break;
}
+ case SK_ListConstructorCall:
+ assert(false && "List constructor calls not yet supported.");
+
case SK_ConstructorInitialization: {
unsigned NumArgs = Args.size();
CXXConstructorDecl *Constructor
= cast<CXXConstructorDecl>(Step->Function.Function);
+ bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
// Build a call to the selected constructor.
ASTOwningVector<Expr*> ConstructorArgs(S);
@@ -4309,6 +4672,7 @@ InitializationSequence::Perform(Sema &S,
Exprs,
NumExprs,
Kind.getParenRange(),
+ HadMultipleCandidates,
ConstructorInitRequiresZeroInit));
} else {
CXXConstructExpr::ConstructionKind ConstructKind =
@@ -4333,6 +4697,7 @@ InitializationSequence::Perform(Sema &S,
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
Constructor, /*Elidable=*/true,
move_arg(ConstructorArgs),
+ HadMultipleCandidates,
ConstructorInitRequiresZeroInit,
ConstructKind,
parenRange);
@@ -4340,6 +4705,7 @@ InitializationSequence::Perform(Sema &S,
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
Constructor,
move_arg(ConstructorArgs),
+ HadMultipleCandidates,
ConstructorInitRequiresZeroInit,
ConstructKind,
parenRange);
@@ -4427,7 +4793,7 @@ InitializationSequence::Perform(Sema &S,
case SK_ObjCObjectConversion:
CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type,
CK_ObjCObjectLValueCast,
- S.CastCategory(CurInit.get()));
+ CurInit.get()->getValueKind());
break;
case SK_ArrayInit:
@@ -4463,7 +4829,7 @@ InitializationSequence::Perform(Sema &S,
case SK_ProduceObjCObject:
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type,
- CK_ObjCProduceObject,
+ CK_ARCProduceObject,
CurInit.take(), 0, VK_RValue));
break;
}
@@ -4759,17 +5125,28 @@ bool InitializationSequence::Diagnose(Sema &S,
}
break;
- case FK_Incomplete:
- S.RequireCompleteType(Kind.getLocation(), DestType,
- diag::err_init_incomplete_type);
- break;
+ case FK_Incomplete:
+ S.RequireCompleteType(Kind.getLocation(), DestType,
+ diag::err_init_incomplete_type);
+ break;
+
+ case FK_ListInitializationFailed: {
+ // Run the init list checker again to emit diagnostics.
+ InitListExpr* InitList = cast<InitListExpr>(Args[0]);
+ QualType DestType = Entity.getType();
+ InitListChecker DiagnoseInitList(S, Entity, InitList,
+ DestType, /*VerifyOnly=*/false);
+ assert(DiagnoseInitList.HadError() &&
+ "Inconsistent init list check result.");
+ break;
+ }
}
PrintInitLocationNote(S, Entity);
return true;
}
-void InitializationSequence::dump(llvm::raw_ostream &OS) const {
+void InitializationSequence::dump(raw_ostream &OS) const {
switch (SequenceKind) {
case FailedSequence: {
OS << "Failed sequence: ";
@@ -4857,6 +5234,9 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case FK_Incomplete:
OS << "initialization of incomplete type";
break;
+
+ case FK_ListInitializationFailed:
+ OS << "list initialization checker failure";
}
OS << '\n';
return;
@@ -4906,7 +5286,7 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
break;
case SK_UserConversion:
- OS << "user-defined conversion via " << S->Function.Function;
+ OS << "user-defined conversion via " << *S->Function.Function;
break;
case SK_QualificationConversionRValue:
@@ -4926,7 +5306,11 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
break;
case SK_ListInitialization:
- OS << "list initialization";
+ OS << "list aggregate initialization";
+ break;
+
+ case SK_ListConstructorCall:
+ OS << "list initialization via constructor";
break;
case SK_ConstructorInitialization:
@@ -4972,6 +5356,51 @@ void InitializationSequence::dump() const {
dump(llvm::errs());
}
+static void DiagnoseNarrowingInInitList(
+ Sema& S, QualType EntityType, const Expr *InitE,
+ bool Constant, const APValue &ConstantValue) {
+ if (Constant) {
+ S.Diag(InitE->getLocStart(),
+ S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt
+ ? diag::err_init_list_constant_narrowing
+ : diag::warn_init_list_constant_narrowing)
+ << InitE->getSourceRange()
+ << ConstantValue
+ << EntityType.getLocalUnqualifiedType();
+ } else
+ S.Diag(InitE->getLocStart(),
+ S.getLangOptions().CPlusPlus0x && !S.getLangOptions().MicrosoftExt
+ ? diag::err_init_list_variable_narrowing
+ : diag::warn_init_list_variable_narrowing)
+ << InitE->getSourceRange()
+ << InitE->getType().getLocalUnqualifiedType()
+ << EntityType.getLocalUnqualifiedType();
+
+ llvm::SmallString<128> StaticCast;
+ llvm::raw_svector_ostream OS(StaticCast);
+ OS << "static_cast<";
+ if (const TypedefType *TT = EntityType->getAs<TypedefType>()) {
+ // It's important to use the typedef's name if there is one so that the
+ // fixit doesn't break code using types like int64_t.
+ //
+ // FIXME: This will break if the typedef requires qualification. But
+ // getQualifiedNameAsString() includes non-machine-parsable components.
+ OS << *TT->getDecl();
+ } else if (const BuiltinType *BT = EntityType->getAs<BuiltinType>())
+ OS << BT->getName(S.getLangOptions());
+ else {
+ // Oops, we didn't find the actual type of the variable. Don't emit a fixit
+ // with a broken cast.
+ return;
+ }
+ OS << ">(";
+ S.Diag(InitE->getLocStart(), diag::note_init_list_narrowing_override)
+ << InitE->getSourceRange()
+ << FixItHint::CreateInsertion(InitE->getLocStart(), OS.str())
+ << FixItHint::CreateInsertion(
+ S.getPreprocessor().getLocForEndOfToken(InitE->getLocEnd()), ")");
+}
+
//===----------------------------------------------------------------------===//
// Initialization helper functions
//===----------------------------------------------------------------------===//
@@ -4993,7 +5422,8 @@ Sema::CanPerformCopyInitialization(const InitializedEntity &Entity,
ExprResult
Sema::PerformCopyInitialization(const InitializedEntity &Entity,
SourceLocation EqualLoc,
- ExprResult Init) {
+ ExprResult Init,
+ bool TopLevelOfInitList) {
if (Init.isInvalid())
return ExprError();
@@ -5007,5 +5437,13 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
EqualLoc);
InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
Init.release();
+
+ bool Constant = false;
+ APValue Result;
+ if (TopLevelOfInitList &&
+ Seq.endsWithNarrowing(Context, InitE, &Constant, &Result)) {
+ DiagnoseNarrowingInInitList(*this, Entity.getType(), InitE,
+ Constant, Result);
+ }
return Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1));
}