summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r--lib/Sema/SemaInit.cpp1322
1 files changed, 713 insertions, 609 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index a28fd7f..b9a6a57 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -11,8 +11,6 @@
// point is Sema::CheckInitList(), but all of the work is performed
// within the InitListChecker class.
//
-// This file also implements Sema::CheckInitializerTypes.
-//
//===----------------------------------------------------------------------===//
#include "clang/Sema/Designator.h"
@@ -122,7 +120,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
/// 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)
+/// arguments, which contains the current "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
@@ -231,11 +229,11 @@ public:
void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
const InitializedEntity &ParentEntity,
- InitListExpr *ILE,
+ InitListExpr *ILE,
bool &RequiresSecondPass) {
SourceLocation Loc = ILE->getSourceRange().getBegin();
unsigned NumInits = ILE->getNumInits();
- InitializedEntity MemberEntity
+ InitializedEntity MemberEntity
= InitializedEntity::InitializeMember(Field, &ParentEntity);
if (Init >= NumInits || !ILE->getInit(Init)) {
// FIXME: We probably don't need to handle references
@@ -254,7 +252,7 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
hadError = true;
return;
}
-
+
InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc,
true);
InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0);
@@ -263,14 +261,14 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
hadError = true;
return;
}
-
+
ExprResult MemberInit
= InitSeq.Perform(SemaRef, MemberEntity, Kind, MultiExprArg());
if (MemberInit.isInvalid()) {
hadError = true;
return;
}
-
+
if (hadError) {
// Do nothing
} else if (Init < NumInits) {
@@ -286,14 +284,14 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
}
} else if (InitListExpr *InnerILE
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
- FillInValueInitializations(MemberEntity, InnerILE,
- RequiresSecondPass);
+ FillInValueInitializations(MemberEntity, InnerILE,
+ RequiresSecondPass);
}
/// Recursively replaces NULL values within the given initializer list
/// with expressions that perform value-initialization of the
/// appropriate type.
-void
+void
InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
InitListExpr *ILE,
bool &RequiresSecondPass) {
@@ -344,17 +342,17 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
ElementType = AType->getElementType();
if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType))
NumElements = CAType->getSize().getZExtValue();
- ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
+ ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
0, Entity);
} else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) {
ElementType = VType->getElementType();
NumElements = VType->getNumElements();
- ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
+ ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context,
0, Entity);
} else
ElementType = ILE->getType();
-
+
for (unsigned Init = 0; Init != NumElements; ++Init) {
if (hadError)
return;
@@ -409,7 +407,7 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
unsigned newStructuredIndex = 0;
FullyStructuredList
= getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange());
- CheckExplicitInitList(Entity, IL, T, newIndex,
+ CheckExplicitInitList(Entity, IL, T, newIndex,
FullyStructuredList, newStructuredIndex,
/*TopLevelObject=*/true);
@@ -417,7 +415,7 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
bool RequiresSecondPass = false;
FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass);
if (RequiresSecondPass && !hadError)
- FillInValueInitializations(Entity, FullyStructuredList,
+ FillInValueInitializations(Entity, FullyStructuredList,
RequiresSecondPass);
}
}
@@ -482,7 +480,7 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
// Check the element types and build the structural subobject.
unsigned StartIndex = Index;
- CheckListElementTypes(Entity, ParentIList, T,
+ CheckListElementTypes(Entity, ParentIList, T,
/*SubobjectIsDesignatorContext=*/false, Index,
StructuredSubobjectInitList,
StructuredSubobjectInitIndex,
@@ -497,16 +495,16 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity,
= 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(StructuredSubobjectInitList->getLocStart(),
"{")
<< FixItHint::CreateInsertion(SemaRef.PP.getLocForEndOfToken(
- StructuredSubobjectInitList->getLocEnd()),
+ StructuredSubobjectInitList->getLocEnd()),
"}");
}
}
@@ -520,7 +518,7 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity,
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
SyntacticToSemantic[IList] = StructuredList;
StructuredList->setSyntacticForm(IList);
- CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
+ CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true,
Index, StructuredList, StructuredIndex, TopLevelObject);
QualType ExprTy = T.getNonLValueExprType(SemaRef.Context);
IList->setType(ExprTy);
@@ -585,7 +583,7 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
CheckScalarType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
} else if (DeclType->isVectorType()) {
- CheckVectorType(Entity, IList, DeclType, Index,
+ CheckVectorType(Entity, IList, DeclType, Index,
StructuredList, StructuredIndex);
} else if (DeclType->isAggregateType()) {
if (DeclType->isRecordType()) {
@@ -598,7 +596,7 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,
llvm::APSInt Zero(
SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()),
false);
- CheckArrayType(Entity, IList, DeclType, Zero,
+ CheckArrayType(Entity, IList, DeclType, Zero,
SubobjectIsDesignatorContext, Index,
StructuredList, StructuredIndex);
} else
@@ -658,7 +656,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
++Index;
} else if (ElemType->isScalarType()) {
- CheckScalarType(Entity, IList, ElemType, Index,
+ CheckScalarType(Entity, IList, ElemType, Index,
StructuredList, StructuredIndex);
} else if (ElemType->isReferenceType()) {
CheckReferenceType(Entity, IList, ElemType, Index,
@@ -672,17 +670,17 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// member, the member is initialized. [...]
// FIXME: Better EqualLoc?
- InitializationKind Kind =
+ InitializationKind Kind =
InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation());
InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
-
+
if (Seq) {
- ExprResult Result =
+ ExprResult Result =
Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
if (Result.isInvalid())
hadError = true;
-
- UpdateStructuredListElement(StructuredList, StructuredIndex,
+
+ UpdateStructuredListElement(StructuredList, StructuredIndex,
Result.takeAs<Expr>());
++Index;
return;
@@ -699,7 +697,9 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// initial value of the object, including unnamed members, is
// that of the expression.
if ((ElemType->isRecordType() || ElemType->isVectorType()) &&
- SemaRef.Context.hasSameUnqualifiedType(expr->getType(), ElemType)) {
+ SemaRef.CheckSingleAssignmentConstraints(ElemType, expr)
+ == Sema::Compatible) {
+ SemaRef.DefaultFunctionArrayLvalueConversion(expr);
UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
++Index;
return;
@@ -721,9 +721,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
} else {
// We cannot initialize this element, so let
// PerformCopyInitialization produce the appropriate diagnostic.
- SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
+ SemaRef.PerformCopyInitialization(Entity, SourceLocation(),
SemaRef.Owned(expr));
- IList->setInit(Index, 0);
hadError = true;
++Index;
++StructuredIndex;
@@ -736,48 +735,7 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
- if (Index < IList->getNumInits()) {
- 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();
-
- 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();
- hadError = true;
- ++Index;
- ++StructuredIndex;
- return;
- }
-
- ExprResult Result =
- SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
- SemaRef.Owned(expr));
-
- Expr *ResultExpr = 0;
-
- if (Result.isInvalid())
- hadError = true; // types weren't compatible.
- else {
- ResultExpr = Result.takeAs<Expr>();
-
- if (ResultExpr != expr) {
- // The type was promoted, update initializer list.
- IList->setInit(Index, ResultExpr);
- }
- }
- if (hadError)
- ++StructuredIndex;
- else
- UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
- ++Index;
- } else {
+ if (Index >= IList->getNumInits()) {
SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer)
<< IList->getSourceRange();
hadError = true;
@@ -785,6 +743,47 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
++StructuredIndex;
return;
}
+
+ 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();
+
+ 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();
+ hadError = true;
+ ++Index;
+ ++StructuredIndex;
+ return;
+ }
+
+ ExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
+ SemaRef.Owned(expr));
+
+ Expr *ResultExpr = 0;
+
+ if (Result.isInvalid())
+ hadError = true; // types weren't compatible.
+ else {
+ ResultExpr = Result.takeAs<Expr>();
+
+ if (ResultExpr != expr) {
+ // The type was promoted, update initializer list.
+ IList->setInit(Index, ResultExpr);
+ }
+ }
+ if (hadError)
+ ++StructuredIndex;
+ else
+ UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
+ ++Index;
}
void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
@@ -839,66 +838,95 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex) {
- if (Index < IList->getNumInits()) {
- const VectorType *VT = DeclType->getAs<VectorType>();
- unsigned maxElements = VT->getNumElements();
- unsigned numEltsInit = 0;
- QualType elementType = VT->getElementType();
-
- if (!SemaRef.getLangOptions().OpenCL) {
- InitializedEntity ElementEntity =
- InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
-
- 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;
-
- ElementEntity.setElementIndex(Index);
- CheckSubElementType(ElementEntity, IList, elementType, Index,
- StructuredList, StructuredIndex);
- }
- } else {
- InitializedEntity ElementEntity =
- InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
-
- // 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;
-
- ElementEntity.setElementIndex(Index);
-
- QualType IType = IList->getInit(Index)->getType();
- if (!IType->isVectorType()) {
- CheckSubElementType(ElementEntity, IList, elementType, Index,
- StructuredList, StructuredIndex);
- ++numEltsInit;
- } else {
- QualType VecType;
- const VectorType *IVT = IType->getAs<VectorType>();
- unsigned numIElts = IVT->getNumElements();
-
- if (IType->isExtVectorType())
- VecType = SemaRef.Context.getExtVectorType(elementType, numIElts);
- else
- VecType = SemaRef.Context.getVectorType(elementType, numIElts,
- IVT->getAltiVecSpecific());
- CheckSubElementType(ElementEntity, IList, VecType, Index,
- StructuredList, StructuredIndex);
- numEltsInit += numIElts;
+ if (Index >= IList->getNumInits())
+ return;
+
+ const VectorType *VT = DeclType->getAs<VectorType>();
+ unsigned maxElements = VT->getNumElements();
+ unsigned numEltsInit = 0;
+ QualType elementType = VT->getElementType();
+
+ if (!SemaRef.getLangOptions().OpenCL) {
+ // If the initializing element is a vector, try to copy-initialize
+ // instead of breaking it apart (which is doomed to failure anyway).
+ Expr *Init = IList->getInit(Index);
+ if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) {
+ ExprResult Result =
+ SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(),
+ SemaRef.Owned(Init));
+
+ Expr *ResultExpr = 0;
+ if (Result.isInvalid())
+ hadError = true; // types weren't compatible.
+ else {
+ ResultExpr = Result.takeAs<Expr>();
+
+ if (ResultExpr != Init) {
+ // The type was promoted, update initializer list.
+ IList->setInit(Index, ResultExpr);
}
}
+ if (hadError)
+ ++StructuredIndex;
+ else
+ UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr);
+ ++Index;
+ return;
}
- // 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;
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+ 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;
+
+ ElementEntity.setElementIndex(Index);
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
+ StructuredList, StructuredIndex);
+ }
+ return;
+ }
+
+ InitializedEntity ElementEntity =
+ InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
+
+ // 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;
+
+ ElementEntity.setElementIndex(Index);
+
+ QualType IType = IList->getInit(Index)->getType();
+ if (!IType->isVectorType()) {
+ CheckSubElementType(ElementEntity, IList, elementType, Index,
+ StructuredList, StructuredIndex);
+ ++numEltsInit;
+ } else {
+ QualType VecType;
+ const VectorType *IVT = IType->getAs<VectorType>();
+ unsigned numIElts = IVT->getNumElements();
+
+ if (IType->isExtVectorType())
+ VecType = SemaRef.Context.getExtVectorType(elementType, numIElts);
+ else
+ VecType = SemaRef.Context.getVectorType(elementType, numIElts,
+ IVT->getVectorKind());
+ CheckSubElementType(ElementEntity, IList, VecType, Index,
+ StructuredList, StructuredIndex);
+ numEltsInit += numIElts;
+ }
}
+
+ // 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;
}
void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
@@ -945,7 +973,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
if (const ConstantArrayType *CAT =
SemaRef.Context.getAsConstantArrayType(DeclType)) {
maxElements = CAT->getSize();
- elementIndex.extOrTrunc(maxElements.getBitWidth());
+ elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth());
elementIndex.setIsUnsigned(maxElements.isUnsigned());
maxElementsKnown = true;
}
@@ -972,9 +1000,9 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
}
if (elementIndex.getBitWidth() > maxElements.getBitWidth())
- maxElements.extend(elementIndex.getBitWidth());
+ maxElements = maxElements.extend(elementIndex.getBitWidth());
else if (elementIndex.getBitWidth() < maxElements.getBitWidth())
- elementIndex.extend(maxElements.getBitWidth());
+ elementIndex = elementIndex.extend(maxElements.getBitWidth());
elementIndex.setIsUnsigned(maxElements.isUnsigned());
// If the array is of incomplete type, keep track of the number of
@@ -991,7 +1019,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
break;
InitializedEntity ElementEntity =
- InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex,
+ InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex,
Entity);
// Check this element.
CheckSubElementType(ElementEntity, IList, elementType, Index,
@@ -1118,7 +1146,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
}
// Emit warnings for missing struct field initializers.
- if (InitializedSomething && CheckForMissingFields && Field != FieldEnd &&
+ if (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.
@@ -1158,12 +1186,12 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
InitializedEntity MemberEntity =
InitializedEntity::InitializeMember(*Field, &Entity);
-
+
if (isa<InitListExpr>(IList->getInit(Index)))
- CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
+ CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
StructuredList, StructuredIndex);
else
- CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
+ CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
StructuredList, StructuredIndex);
}
@@ -1171,34 +1199,25 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
/// 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,
DesignatedInitExpr *DIE,
unsigned DesigIdx,
- FieldDecl *Field,
- RecordDecl::field_iterator &FieldIter,
- unsigned &FieldIndex) {
+ IndirectFieldDecl *IndirectField) {
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);
-
// 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)
+ for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
+ PE = IndirectField->chain_end(); PI != PE; ++PI) {
+ if (PI + 1 == PE)
Replacements.push_back(Designator((IdentifierInfo *)0,
DIE->getDesignator(DesigIdx)->getDotLoc(),
DIE->getDesignator(DesigIdx)->getFieldLoc()));
else
Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
SourceLocation()));
- Replacements.back().setField(*FI);
+ assert(isa<FieldDecl>(*PI));
+ Replacements.back().setField(cast<FieldDecl>(*PI));
}
// Expand the current designator into the set of replacement
@@ -1206,23 +1225,20 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
// member of the anonymous struct/union is actually stored.
DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0],
&Replacements[0] + Replacements.size());
+}
- // Update FieldIter/FieldIndex;
- RecordDecl *Record = cast<RecordDecl>(Path.back()->getDeclContext());
- FieldIter = Record->field_begin();
- FieldIndex = 0;
- for (RecordDecl::field_iterator FEnd = Record->field_end();
- FieldIter != FEnd; ++FieldIter) {
- if (FieldIter->isUnnamedBitfield())
- continue;
-
- if (*FieldIter == Path.back())
- return;
-
- ++FieldIndex;
+/// \brief Given an implicit anonymous field, search the IndirectField that
+/// corresponds to FieldName.
+static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
+ IdentifierInfo *FieldName) {
+ assert(AnonField->isAnonymousStructOrUnion());
+ Decl *NextDecl = AnonField->getNextDeclInContext();
+ while (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(NextDecl)) {
+ if (FieldName && FieldName == IF->getAnonField()->getIdentifier())
+ return IF;
+ NextDecl = NextDecl->getNextDeclInContext();
}
-
- assert(false && "Unable to find anonymous struct/union field");
+ return 0;
}
/// @brief Check the well-formedness of a C99 designated initializer.
@@ -1343,7 +1359,19 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (Field->isUnnamedBitfield())
continue;
- if (KnownField == *Field || Field->getIdentifier() == FieldName)
+ // If we find a field representing an anonymous field, look in the
+ // IndirectFieldDecl that follow for the designated initializer.
+ if (!KnownField && Field->isAnonymousStructOrUnion()) {
+ if (IndirectFieldDecl *IF =
+ FindIndirectFieldDesignator(*Field, FieldName)) {
+ ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF);
+ D = DIE->getDesignator(DesigIdx);
+ break;
+ }
+ }
+ if (KnownField && KnownField == *Field)
+ break;
+ if (FieldName && FieldName == Field->getIdentifier())
break;
++FieldIndex;
@@ -1360,19 +1388,19 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (Lookup.first == Lookup.second) {
// Name lookup didn't find anything. Determine whether this
// was a typo for another field name.
- LookupResult R(SemaRef, FieldName, D->getFieldLoc(),
+ LookupResult R(SemaRef, FieldName, D->getFieldLoc(),
Sema::LookupMemberName);
if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false,
- Sema::CTC_NoKeywords) &&
+ Sema::CTC_NoKeywords) &&
(ReplacementField = R.getAsSingle<FieldDecl>()) &&
ReplacementField->getDeclContext()->getRedeclContext()
->Equals(RT->getDecl())) {
- SemaRef.Diag(D->getFieldLoc(),
+ SemaRef.Diag(D->getFieldLoc(),
diag::err_field_designator_unknown_suggest)
<< FieldName << CurrentObjectType << R.getLookupName()
<< FixItHint::CreateReplacement(D->getFieldLoc(),
R.getLookupName().getAsString());
- SemaRef.Diag(ReplacementField->getLocation(),
+ SemaRef.Diag(ReplacementField->getLocation(),
diag::note_previous_decl)
<< ReplacementField->getDeclName();
} else {
@@ -1381,9 +1409,6 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
++Index;
return true;
}
- } else if (!KnownField) {
- // Determine whether we found a field at all.
- ReplacementField = dyn_cast<FieldDecl>(*Lookup.first);
}
if (!ReplacementField) {
@@ -1396,16 +1421,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
return true;
}
- if (!KnownField &&
- cast<RecordDecl>((ReplacementField)->getDeclContext())
- ->isAnonymousStructOrUnion()) {
- // Handle an field designator that refers to a member of an
- // anonymous struct or union.
- ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx,
- ReplacementField,
- Field, FieldIndex);
- D = DIE->getDesignator(DesigIdx);
- } else if (!KnownField) {
+ if (!KnownField) {
// The replacement field comes from typo correction; find it
// in the list of fields.
FieldIndex = 0;
@@ -1414,19 +1430,13 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (Field->isUnnamedBitfield())
continue;
- if (ReplacementField == *Field ||
+ if (ReplacementField == *Field ||
Field->getIdentifier() == ReplacementField->getIdentifier())
break;
++FieldIndex;
}
}
- } else if (!KnownField &&
- cast<RecordDecl>((*Field)->getDeclContext())
- ->isAnonymousStructOrUnion()) {
- ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, *Field,
- Field, FieldIndex);
- D = DIE->getDesignator(DesigIdx);
}
// All of the fields of a union are located at the same place in
@@ -1461,7 +1471,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
Invalid = true;
}
- if (!hadError && !isa<InitListExpr>(DIE->getInit())) {
+ 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)
@@ -1511,11 +1522,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Recurse to check later designated subobjects.
QualType FieldType = (*Field)->getType();
unsigned newStructuredIndex = FieldIndex;
-
+
InitializedEntity MemberEntity =
InitializedEntity::InitializeMember(*Field, &Entity);
- if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
- FieldType, 0, 0, Index,
+ if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1,
+ FieldType, 0, 0, Index,
StructuredList, newStructuredIndex,
true, false))
return true;
@@ -1544,7 +1555,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Check the remaining fields within this class/struct/union subobject.
bool prevHadError = hadError;
-
+
CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index,
StructuredList, FieldIndex);
return hadError && !prevHadError;
@@ -1582,22 +1593,29 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
} else {
assert(D->isArrayRangeDesignator() && "Need array-range designator");
-
DesignatedStartIndex =
DIE->getArrayRangeStart(*D)->EvaluateAsInt(SemaRef.Context);
DesignatedEndIndex =
DIE->getArrayRangeEnd(*D)->EvaluateAsInt(SemaRef.Context);
IndexExpr = DIE->getArrayRangeEnd(*D);
- if (DesignatedStartIndex.getZExtValue() !=DesignatedEndIndex.getZExtValue())
+ // Codegen can't handle evaluating array range designators that have side
+ // effects, because we replicate the AST value for each initialized element.
+ // As such, set the sawArrayRangeDesignator() bit if we initialize multiple
+ // 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))
FullyStructuredList->sawArrayRangeDesignator();
}
if (isa<ConstantArrayType>(AT)) {
llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
- DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
+ DesignatedStartIndex
+ = DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
- DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
+ DesignatedEndIndex
+ = DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
if (DesignatedEndIndex >= MaxElements) {
SemaRef.Diag(IndexExpr->getSourceRange().getBegin(),
@@ -1610,10 +1628,12 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
} else {
// Make sure the bit-widths and signedness match.
if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth())
- DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
+ DesignatedEndIndex
+ = DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
else if (DesignatedStartIndex.getBitWidth() <
DesignatedEndIndex.getBitWidth())
- DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
+ DesignatedStartIndex
+ = DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
DesignatedStartIndex.setIsUnsigned(true);
DesignatedEndIndex.setIsUnsigned(true);
}
@@ -1630,7 +1650,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Move to the next designator
unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
unsigned OldIndex = Index;
-
+
InitializedEntity ElementEntity =
InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity);
@@ -1638,10 +1658,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Recurse to check later designated subobjects.
QualType ElementType = AT->getElementType();
Index = OldIndex;
-
+
ElementEntity.setElementIndex(ElementIndex);
- if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
- ElementType, 0, 0, Index,
+ if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1,
+ ElementType, 0, 0, Index,
StructuredList, ElementIndex,
(DesignatedStartIndex == DesignatedEndIndex),
false))
@@ -1666,7 +1686,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Check the remaining elements within this array subobject.
bool prevHadError = hadError;
- CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex,
+ CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex,
/*SubobjectIsDesignatorContext=*/false, Index,
StructuredList, ElementIndex);
return hadError && !prevHadError;
@@ -1812,9 +1832,9 @@ CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
}
ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
- SourceLocation Loc,
- bool GNUSyntax,
- ExprResult Init) {
+ SourceLocation Loc,
+ bool GNUSyntax,
+ ExprResult Init) {
typedef DesignatedInitExpr::Designator ASTDesignator;
bool Invalid = false;
@@ -1865,9 +1885,9 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
if (StartDependent || EndDependent) {
// Nothing to compute.
} else if (StartValue.getBitWidth() > EndValue.getBitWidth())
- EndValue.extend(StartValue.getBitWidth());
+ EndValue = EndValue.extend(StartValue.getBitWidth());
else if (StartValue.getBitWidth() < EndValue.getBitWidth())
- StartValue.extend(EndValue.getBitWidth());
+ StartValue = StartValue.extend(EndValue.getBitWidth());
if (!StartDependent && !EndDependent && EndValue < StartValue) {
Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range)
@@ -1899,6 +1919,11 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
Designators.data(), Designators.size(),
InitExpressions.data(), InitExpressions.size(),
Loc, GNUSyntax, Init.takeAs<Expr>());
+
+ if (getLangOptions().CPlusPlus)
+ Diag(DIE->getLocStart(), diag::ext_designated_init)
+ << DIE->getSourceRange();
+
return Owned(DIE);
}
@@ -1915,9 +1940,9 @@ bool Sema::CheckInitList(const InitializedEntity &Entity,
// Initialization entity
//===----------------------------------------------------------------------===//
-InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
+InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
const InitializedEntity &Parent)
- : Parent(&Parent), Index(Index)
+ : Parent(&Parent), Index(Index)
{
if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) {
Kind = EK_ArrayElement;
@@ -1928,7 +1953,7 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index,
}
}
-InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
+InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
CXXBaseSpecifier *Base,
bool IsInheritedVirtualBase)
{
@@ -1937,7 +1962,7 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
Result.Base = reinterpret_cast<uintptr_t>(Base);
if (IsInheritedVirtualBase)
Result.Base |= 0x01;
-
+
Result.Type = Base->getType();
return Result;
}
@@ -1963,7 +1988,7 @@ DeclarationName InitializedEntity::getName() const {
case EK_BlockElement:
return DeclarationName();
}
-
+
// Silence GCC warning
return DeclarationName();
}
@@ -1985,7 +2010,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const {
case EK_BlockElement:
return 0;
}
-
+
// Silence GCC warning
return 0;
}
@@ -1995,7 +2020,7 @@ bool InitializedEntity::allowsNRVO() const {
case EK_Result:
case EK_Exception:
return LocAndNRVO.NRVO;
-
+
case EK_Variable:
case EK_Parameter:
case EK_Member:
@@ -2035,7 +2060,7 @@ void InitializationSequence::Step::Destroy() {
case SK_StringInit:
case SK_ObjCObjectConversion:
break;
-
+
case SK_ConversionSequence:
delete ICS;
}
@@ -2048,7 +2073,7 @@ bool InitializationSequence::isDirectReferenceBinding() const {
bool InitializationSequence::isAmbiguous() const {
if (getKind() != FailedSequence)
return false;
-
+
switch (getFailureKind()) {
case FK_TooManyInitsForReference:
case FK_ArrayNeedsInitList:
@@ -2066,13 +2091,13 @@ bool InitializationSequence::isAmbiguous() const {
case FK_DefaultInitOfConst:
case FK_Incomplete:
return false;
-
+
case FK_ReferenceInitOverloadFailed:
case FK_UserConversionOverloadFailed:
case FK_ConstructorOverloadFailed:
return FailedOverloadResult == OR_Ambiguous;
}
-
+
return false;
}
@@ -2091,7 +2116,7 @@ void InitializationSequence::AddAddressOverloadResolutionStep(
Steps.push_back(S);
}
-void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
+void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
ExprValueKind VK) {
Step S;
switch (VK) {
@@ -2104,7 +2129,7 @@ void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
Steps.push_back(S);
}
-void InitializationSequence::AddReferenceBindingStep(QualType T,
+void InitializationSequence::AddReferenceBindingStep(QualType T,
bool BindingTemporary) {
Step S;
S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference;
@@ -2166,7 +2191,7 @@ void InitializationSequence::AddListInitializationStep(QualType T) {
Steps.push_back(S);
}
-void
+void
InitializationSequence::AddConstructorInitializationStep(
CXXConstructorDecl *Constructor,
AccessSpecifier Access,
@@ -2207,7 +2232,7 @@ void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
Steps.push_back(S);
}
-void InitializationSequence::SetOverloadFailure(FailureKind Failure,
+void InitializationSequence::SetOverloadFailure(FailureKind Failure,
OverloadingResult Result) {
SequenceKind = FailedSequence;
this->Failure = Failure;
@@ -2218,8 +2243,8 @@ void InitializationSequence::SetOverloadFailure(FailureKind Failure,
// Attempt initialization
//===----------------------------------------------------------------------===//
-/// \brief Attempt list initialization (C++0x [dcl.init.list])
-static void TryListInitialization(Sema &S,
+/// \brief Attempt list initialization (C++0x [dcl.init.list])
+static void TryListInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
InitListExpr *InitList,
@@ -2235,7 +2260,7 @@ static void TryListInitialization(Sema &S,
QualType DestType = Entity.getType();
// C++ [dcl.init]p13:
- // If T is a scalar type, then a declaration of the form
+ // If T is a scalar type, then a declaration of the form
//
// T x = { a };
//
@@ -2282,7 +2307,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
bool DerivedToBase;
bool ObjCConversion;
- assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
+ assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
T1, T2, DerivedToBase,
ObjCConversion) &&
"Must have incompatible references when binding via conversion");
@@ -2297,7 +2322,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
-
+
const RecordType *T1RecordType = 0;
if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
!S.RequireCompleteType(Kind.getLocation(), T1, 0)) {
@@ -2319,22 +2344,24 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
-
+
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
- &Initializer, 1, CandidateSet);
+ &Initializer, 1, CandidateSet,
+ /*SuppressUserConversions=*/true);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
- &Initializer, 1, CandidateSet);
+ &Initializer, 1, CandidateSet,
+ /*SuppressUserConversions=*/true);
}
- }
+ }
}
if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
return OR_No_Viable_Function;
-
+
const RecordType *T2RecordType = 0;
if ((T2RecordType = T2->getAs<RecordType>()) &&
!S.RequireCompleteType(Kind.getLocation(), T2, 0)) {
@@ -2342,11 +2369,6 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// functions.
CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
- // Determine the type we are converting to. If we are allowed to
- // convert to an rvalue, take the type that the destination type
- // refers to.
- QualType ToType = AllowRValues? cv1T1 : DestType;
-
const UnresolvedSetImpl *Conversions
= T2RecordDecl->getVisibleConversionFunctions();
for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
@@ -2355,41 +2377,41 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
-
+
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
CXXConversionDecl *Conv;
if (ConvTemplate)
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
Conv = cast<CXXConversionDecl>(D);
-
+
// If the conversion function doesn't return a reference type,
// it can't be considered for this conversion unless we're allowed to
// consider rvalues.
- // FIXME: Do we need to make sure that we only consider conversion
- // candidates with reference-compatible results? That might be needed to
+ // FIXME: Do we need to make sure that we only consider conversion
+ // candidates with reference-compatible results? That might be needed to
// break recursion.
if ((AllowExplicit || !Conv->isExplicit()) &&
(AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
ActingDC, Initializer,
- ToType, CandidateSet);
+ DestType, CandidateSet);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
- Initializer, ToType, CandidateSet);
+ Initializer, DestType, CandidateSet);
}
}
}
if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
return OR_No_Viable_Function;
-
+
SourceLocation DeclLoc = Initializer->getLocStart();
- // Perform overload resolution. If it fails, return the failed result.
+ // Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
- if (OverloadingResult Result
- = CandidateSet.BestViableFunction(S, DeclLoc, Best))
+ if (OverloadingResult Result
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best, true))
return Result;
FunctionDecl *Function = Best->Function;
@@ -2404,7 +2426,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
Sequence.AddUserConversionStep(Function, Best->FoundDecl,
T2.getNonLValueExprType(S.Context));
- // Determine whether we need to perform derived-to-base or
+ // Determine whether we need to perform derived-to-base or
// cv-qualification adjustments.
ExprValueKind VK = VK_RValue;
if (T2->isLValueReferenceType())
@@ -2415,7 +2437,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
bool NewDerivedToBase = false;
bool NewObjCConversion = false;
Sema::ReferenceCompareResult NewRefRelationship
- = S.CompareReferenceRelationship(DeclLoc, T1,
+ = S.CompareReferenceRelationship(DeclLoc, T1,
T2.getNonLValueExprType(S.Context),
NewDerivedToBase, NewObjCConversion);
if (NewRefRelationship == Sema::Ref_Incompatible) {
@@ -2431,7 +2453,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
} else if (NewDerivedToBase)
Sequence.AddDerivedToBaseCastStep(
S.Context.getQualifiedType(T1,
- T2.getNonReferenceType().getQualifiers()),
+ T2.getNonReferenceType().getQualifiers()),
VK);
else if (NewObjCConversion)
Sequence.AddObjCObjectConversionStep(
@@ -2440,13 +2462,13 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
Sequence.AddQualificationConversionStep(cv1T1, VK);
-
+
Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
return OR_Success;
}
-
-/// \brief Attempt reference initialization (C++0x [dcl.init.ref])
-static void TryReferenceInitialization(Sema &S,
+
+/// \brief Attempt reference initialization (C++0x [dcl.init.ref])
+static void TryReferenceInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expr *Initializer,
@@ -2467,18 +2489,17 @@ static void TryReferenceInitialization(Sema &S,
// type of the resulting function.
if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
DeclAccessPair Found;
- FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer,
- T1,
- false,
- Found);
- if (!Fn) {
+ if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer,
+ T1,
+ false,
+ Found)) {
+ Sequence.AddAddressOverloadResolutionStep(Fn, Found);
+ cv2T2 = Fn->getType();
+ T2 = cv2T2.getUnqualifiedType();
+ } else if (!T1->isRecordType()) {
Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
return;
}
-
- Sequence.AddAddressOverloadResolutionStep(Fn, Found);
- cv2T2 = Fn->getType();
- T2 = cv2T2.getUnqualifiedType();
}
// Compute some basic properties of the types and the initializer.
@@ -2492,10 +2513,10 @@ static void TryReferenceInitialization(Sema &S,
ObjCConversion);
// C++0x [dcl.init.ref]p5:
- // A reference to type "cv1 T1" is initialized by an expression of type
+ // A reference to type "cv1 T1" is initialized by an expression of type
// "cv2 T2" as follows:
//
- // - If the reference is an lvalue reference and the initializer
+ // - If the reference is an lvalue reference and the initializer
// expression
// Note the analogous bullet points for rvlaue refs to functions. Because
// there are no function rvalues in C++, rvalue refs to functions are treated
@@ -2503,19 +2524,21 @@ static void TryReferenceInitialization(Sema &S,
OverloadingResult ConvOvlResult = OR_Success;
bool T1Function = T1->isFunctionType();
if (isLValueRef || T1Function) {
- if (InitCategory.isLValue() &&
- RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
- // - is an lvalue (but is not a bit-field), and "cv1 T1" is
+ if (InitCategory.isLValue() &&
+ (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
+ (Kind.isCStyleOrFunctionalCast() &&
+ RefRelationship == Sema::Ref_Related))) {
+ // - is an lvalue (but is not a bit-field), and "cv1 T1" is
// reference-compatible with "cv2 T2," or
//
- // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a
+ // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a
// bit-field when we're determining whether the reference initialization
// can occur. However, we do pay attention to whether it is a bit-field
// to decide whether we're actually binding to a temporary created from
// the bit-field.
if (DerivedToBase)
Sequence.AddDerivedToBaseCastStep(
- S.Context.getQualifiedType(T1, T2Quals),
+ S.Context.getQualifiedType(T1, T2Quals),
VK_LValue);
else if (ObjCConversion)
Sequence.AddObjCObjectConversionStep(
@@ -2528,18 +2551,18 @@ static void TryReferenceInitialization(Sema &S,
Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
return;
}
-
- // - has a class type (i.e., T2 is a class type), where T1 is not
- // reference-related to T2, and can be implicitly converted to an
- // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible
- // with "cv3 T3" (this conversion is selected by enumerating the
+
+ // - has a class type (i.e., T2 is a class type), where T1 is not
+ // reference-related to T2, and can be implicitly converted to an
+ // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible
+ // with "cv3 T3" (this conversion is selected by enumerating the
// applicable conversion functions (13.3.1.6) and choosing the best
// one through overload resolution (13.3)),
// If we have an rvalue ref to function type here, the rhs must be
// an rvalue.
if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() &&
(isLValueRef || InitCategory.isRValue())) {
- ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
+ ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
Initializer,
/*AllowRValues=*/isRValueRef,
Sequence);
@@ -2553,37 +2576,39 @@ static void TryReferenceInitialization(Sema &S,
}
}
- // - Otherwise, the reference shall be an lvalue reference to a
+ // - Otherwise, the reference shall be an lvalue reference to a
// non-volatile const type (i.e., cv1 shall be const), or the reference
- // shall be an rvalue reference and the initializer expression shall
- // be an rvalue or have a function type.
- // We handled the function type stuff above.
- if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) ||
- (isRValueRef && InitCategory.isRValue()))) {
- if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+ // shall be an rvalue reference.
+ if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) {
+ if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
+ Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
Sequence.SetOverloadFailure(
InitializationSequence::FK_ReferenceInitOverloadFailed,
ConvOvlResult);
- else if (isLValueRef)
+ else
Sequence.SetFailed(InitCategory.isLValue()
? (RefRelationship == Sema::Ref_Related
? InitializationSequence::FK_ReferenceInitDropsQualifiers
: InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
: InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
- else
- Sequence.SetFailed(
- InitializationSequence::FK_RValueReferenceBindingToLValue);
return;
}
- // - [If T1 is not a function type], if T2 is a class type and
- if (!T1Function && T2->isRecordType()) {
- bool isXValue = InitCategory.isXValue();
- // - the initializer expression is an rvalue and "cv1 T1" is
- // reference-compatible with "cv2 T2", or
- if (InitCategory.isRValue() &&
- RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+ // - If the initializer expression
+ // - is an xvalue, class prvalue, array prvalue, or function lvalue and
+ // "cv1 T1" is reference-compatible with "cv2 T2"
+ // Note: functions are handled below.
+ if (!T1Function &&
+ (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification ||
+ (Kind.isCStyleOrFunctionalCast() &&
+ RefRelationship == Sema::Ref_Related)) &&
+ (InitCategory.isXValue() ||
+ (InitCategory.isPRValue() && T2->isRecordType()) ||
+ (InitCategory.isPRValue() && T2->isArrayType()))) {
+ ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue;
+ if (InitCategory.isPRValue() && T2->isRecordType()) {
// The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
// compiler the freedom to perform a copy here or bind to the
// object, while C++0x requires that we bind directly to the
@@ -2593,29 +2618,29 @@ 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)
+ if (!S.getLangOptions().CPlusPlus0x && !S.getLangOptions().Microsoft)
Sequence.AddExtraneousCopyToTemporary(cv2T2);
-
- if (DerivedToBase)
- Sequence.AddDerivedToBaseCastStep(
- S.Context.getQualifiedType(T1, T2Quals),
- isXValue ? VK_XValue : VK_RValue);
- else if (ObjCConversion)
- Sequence.AddObjCObjectConversionStep(
- S.Context.getQualifiedType(T1, T2Quals));
-
- if (T1Quals != T2Quals)
- Sequence.AddQualificationConversionStep(cv1T1,
- isXValue ? VK_XValue : VK_RValue);
- Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/!isXValue);
- return;
}
- // - T1 is not reference-related to T2 and the initializer expression
- // can be implicitly converted to an rvalue of type "cv3 T3" (this
- // conversion is selected by enumerating the applicable conversion
- // functions (13.3.1.6) and choosing the best one through overload
- // resolution (13.3)),
+ if (DerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals),
+ ValueKind);
+ else if (ObjCConversion)
+ Sequence.AddObjCObjectConversionStep(
+ S.Context.getQualifiedType(T1, T2Quals));
+
+ if (T1Quals != T2Quals)
+ Sequence.AddQualificationConversionStep(cv1T1, ValueKind);
+ Sequence.AddReferenceBindingStep(cv1T1,
+ /*bindingTemporary=*/(InitCategory.isPRValue() && !T2->isArrayType()));
+ return;
+ }
+
+ // - has a class type (i.e., T2 is a class type), where T1 is not
+ // reference-related to T2, and can be implicitly converted to an
+ // xvalue, class prvalue, or function lvalue of type "cv3 T3",
+ // where "cv1 T1" is reference-compatible with "cv3 T3",
+ if (T2->isRecordType()) {
if (RefRelationship == Sema::Ref_Incompatible) {
ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
Kind, Initializer,
@@ -2625,23 +2650,17 @@ static void TryReferenceInitialization(Sema &S,
Sequence.SetOverloadFailure(
InitializationSequence::FK_ReferenceInitOverloadFailed,
ConvOvlResult);
-
+
return;
}
-
+
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
return;
}
-
- // - If the initializer expression is an rvalue, with T2 an array type,
- // and "cv1 T1" is reference-compatible with "cv2 T2," the reference
- // is bound to the object represented by the rvalue (see 3.10).
- // FIXME: How can an array type be reference-compatible with anything?
- // Don't we mean the element types of T1 and T2?
-
- // - Otherwise, a temporary of type “cv1 T1” is created and initialized
+
+ // - Otherwise, a temporary of type "cv1 T1" is created and initialized
// from the initializer expression using the rules for a non-reference
- // copy initialization (8.5). The reference is then bound to the
+ // copy initialization (8.5). The reference is then bound to the
// temporary. [...]
// Determine whether we are allowed to call explicit constructors or
@@ -2653,7 +2672,8 @@ static void TryReferenceInitialization(Sema &S,
if (S.TryImplicitConversion(Sequence, TempEntity, Initializer,
/*SuppressUserConversions*/ false,
AllowExplicit,
- /*FIXME:InOverloadResolution=*/false)) {
+ /*FIXME:InOverloadResolution=*/false,
+ /*CStyle=*/Kind.isCStyleOrFunctionalCast())) {
// FIXME: Use the conversion function set stored in ICS to turn
// this into an overloading ambiguity diagnostic. However, we need
// to keep that set as an OverloadCandidateSet rather than as some
@@ -2662,6 +2682,8 @@ static void TryReferenceInitialization(Sema &S,
Sequence.SetOverloadFailure(
InitializationSequence::FK_ReferenceInitOverloadFailed,
ConvOvlResult);
+ else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
+ Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
else
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
return;
@@ -2672,19 +2694,28 @@ static void TryReferenceInitialization(Sema &S,
// than, cv2; otherwise, the program is ill-formed.
unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
- if (RefRelationship == Sema::Ref_Related &&
+ if (RefRelationship == Sema::Ref_Related &&
(T1CVRQuals | T2CVRQuals) != T1CVRQuals) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
return;
}
+ // [...] If T1 is reference-related to T2 and the reference is an rvalue
+ // reference, the initializer expression shall not be an lvalue.
+ if (RefRelationship >= Sema::Ref_Related && !isLValueRef &&
+ InitCategory.isLValue()) {
+ Sequence.SetFailed(
+ InitializationSequence::FK_RValueReferenceBindingToLValue);
+ return;
+ }
+
Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
return;
}
/// \brief Attempt character array initialization from a string literal
-/// (C++ [dcl.init.string], C99 6.7.8).
-static void TryStringLiteralInitialization(Sema &S,
+/// (C++ [dcl.init.string], C99 6.7.8).
+static void TryStringLiteralInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expr *Initializer,
@@ -2696,19 +2727,19 @@ static void TryStringLiteralInitialization(Sema &S,
/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
/// enumerates the constructors of the initialized entity and performs overload
/// resolution to select the best.
-static void TryConstructorInitialization(Sema &S,
+static void TryConstructorInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expr **Args, unsigned NumArgs,
QualType DestType,
InitializationSequence &Sequence) {
Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
-
+
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
CandidateSet.clear();
-
+
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
@@ -2720,21 +2751,21 @@ static void TryConstructorInitialization(Sema &S,
Sequence.SetFailed(InitializationSequence::FK_Incomplete);
return;
}
-
+
// The type we're converting to is a class type. Enumerate its constructors
// to see if one is suitable.
const RecordType *DestRecordType = DestType->getAs<RecordType>();
- assert(DestRecordType && "Constructor initialization requires record type");
+ assert(DestRecordType && "Constructor initialization requires record type");
CXXRecordDecl *DestRecordDecl
= cast<CXXRecordDecl>(DestRecordType->getDecl());
-
+
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
bool SuppressUserConversions = false;
-
+
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
@@ -2744,14 +2775,14 @@ static void TryConstructorInitialization(Sema &S,
else {
Constructor = cast<CXXConstructorDecl>(D);
- // If we're performing copy initialization using a copy constructor, we
+ // If we're performing copy initialization using a copy constructor, we
// suppress user-defined conversions on the arguments.
// FIXME: Move constructors?
if (Kind.getKind() == InitializationKind::IK_Copy &&
Constructor->isCopyConstructor())
SuppressUserConversions = true;
}
-
+
if (!Constructor->isInvalidDecl() &&
(AllowExplicit || !Constructor->isExplicit())) {
if (ConstructorTmpl)
@@ -2764,16 +2795,16 @@ static void TryConstructorInitialization(Sema &S,
Args, NumArgs, CandidateSet,
SuppressUserConversions);
}
- }
-
+ }
+
SourceLocation DeclLoc = Kind.getLocation();
-
- // Perform overload resolution. If it fails, return the failed result.
+
+ // Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
- if (OverloadingResult Result
+ if (OverloadingResult Result
= CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
Sequence.SetOverloadFailure(
- InitializationSequence::FK_ConstructorOverloadFailed,
+ InitializationSequence::FK_ConstructorOverloadFailed,
Result);
return;
}
@@ -2792,13 +2823,13 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
Sequence.AddConstructorInitializationStep(
- cast<CXXConstructorDecl>(Best->Function),
+ cast<CXXConstructorDecl>(Best->Function),
Best->FoundDecl.getAccess(),
DestType);
}
/// \brief Attempt value initialization (C++ [dcl.init]p7).
-static void TryValueInitialization(Sema &S,
+static void TryValueInitialization(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
InitializationSequence &Sequence) {
@@ -2806,11 +2837,11 @@ static void TryValueInitialization(Sema &S,
//
// To value-initialize an object of type T means:
QualType T = Entity.getType();
-
+
// -- if T is an array type, then each element is value-initialized;
while (const ArrayType *AT = S.Context.getAsArrayType(T))
T = AT->getElementType();
-
+
if (const RecordType *RT = T->getAs<RecordType>()) {
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
// -- if T is a class type (clause 9) with a user-declared
@@ -2822,15 +2853,15 @@ static void TryValueInitialization(Sema &S,
// but Entity doesn't have a way to capture that (yet).
if (ClassDecl->hasUserDeclaredConstructor())
return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
-
+
// -- if T is a (possibly cv-qualified) non-union class type
// without a user-provided constructor, then the object is
- // zero-initialized and, if T’s implicitly-declared default
+ // zero-initialized and, if T's implicitly-declared default
// constructor is non-trivial, that constructor is called.
if ((ClassDecl->getTagKind() == TTK_Class ||
ClassDecl->getTagKind() == TTK_Struct)) {
Sequence.AddZeroInitializationStep(Entity.getType());
- return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
+ return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence);
}
}
}
@@ -2845,14 +2876,14 @@ static void TryDefaultInitialization(Sema &S,
const InitializationKind &Kind,
InitializationSequence &Sequence) {
assert(Kind.getKind() == InitializationKind::IK_Default);
-
+
// C++ [dcl.init]p6:
// To default-initialize an object of type T means:
// - if T is an array type, each element is default-initialized;
QualType DestType = Entity.getType();
while (const ArrayType *Array = S.Context.getAsArrayType(DestType))
DestType = Array->getElementType();
-
+
// - if T is a (possibly cv-qualified) class type (Clause 9), the default
// constructor for T is called (and the initialization is ill-formed if
// T has no accessible default constructor);
@@ -2860,12 +2891,12 @@ static void TryDefaultInitialization(Sema &S,
TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence);
return;
}
-
+
// - otherwise, no initialization is performed.
Sequence.setSequenceKind(InitializationSequence::NoInitialization);
-
+
// If a program calls for the default initialization of an object of
- // a const-qualified type T, T shall be a class type with a user-provided
+ // a const-qualified type T, T shall be a class type with a user-provided
// default constructor.
if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus)
Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
@@ -2874,42 +2905,42 @@ static void TryDefaultInitialization(Sema &S,
/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
/// which enumerates all conversion functions and performs overload resolution
/// to select the best.
-static void TryUserDefinedConversion(Sema &S,
+static void TryUserDefinedConversion(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expr *Initializer,
InitializationSequence &Sequence) {
Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion);
-
+
QualType DestType = Entity.getType();
assert(!DestType->isReferenceType() && "References are handled elsewhere");
QualType SourceType = Initializer->getType();
assert((DestType->isRecordType() || SourceType->isRecordType()) &&
"Must have a class type to perform a user-defined conversion");
-
+
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
CandidateSet.clear();
-
+
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
-
+
if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) {
// The type we're converting to is a class type. Enumerate its constructors
// to see if there is a suitable conversion.
CXXRecordDecl *DestRecordDecl
= cast<CXXRecordDecl>(DestRecordType->getDecl());
-
+
// Try to complete the type we're converting to.
- if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+ if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-
+
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
@@ -2919,7 +2950,7 @@ static void TryUserDefinedConversion(Sema &S,
ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
-
+
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
@@ -2932,7 +2963,7 @@ static void TryUserDefinedConversion(Sema &S,
&Initializer, 1, CandidateSet,
/*SuppressUserConversions=*/true);
}
- }
+ }
}
}
@@ -2947,24 +2978,24 @@ static void TryUserDefinedConversion(Sema &S,
if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) {
CXXRecordDecl *SourceRecordDecl
= cast<CXXRecordDecl>(SourceRecordType->getDecl());
-
+
const UnresolvedSetImpl *Conversions
= SourceRecordDecl->getVisibleConversionFunctions();
for (UnresolvedSetImpl::const_iterator I = Conversions->begin(),
- E = Conversions->end();
+ E = Conversions->end();
I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
-
+
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
CXXConversionDecl *Conv;
if (ConvTemplate)
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
Conv = cast<CXXConversionDecl>(D);
-
+
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
@@ -2977,19 +3008,19 @@ static void TryUserDefinedConversion(Sema &S,
}
}
}
-
- // Perform overload resolution. If it fails, return the failed result.
+
+ // Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
- = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
Sequence.SetOverloadFailure(
- InitializationSequence::FK_UserConversionOverloadFailed,
+ InitializationSequence::FK_UserConversionOverloadFailed,
Result);
return;
}
FunctionDecl *Function = Best->Function;
-
+
if (isa<CXXConstructorDecl>(Function)) {
// Add the user-defined conversion step. Any cv-qualification conversion is
// subsumed by the initialization.
@@ -3011,7 +3042,7 @@ static void TryUserDefinedConversion(Sema &S,
}
Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType);
-
+
// If the conversion following the call to the conversion function
// is interesting, add it as a separate step.
if (Best->FinalConversion.First || Best->FinalConversion.Second ||
@@ -3030,12 +3061,12 @@ InitializationSequence::InitializationSequence(Sema &S,
unsigned NumArgs)
: FailedCandidateSet(Kind.getLocation()) {
ASTContext &Context = S.Context;
-
+
// C++0x [dcl.init]p16:
- // The semantics of initializers are as follows. The destination type is
- // the type of the object or reference being initialized and the source
+ // The semantics of initializers are as follows. The destination type is
+ // the type of the object or reference being initialized and the source
// type is the type of the initializer expression. The source type is not
- // defined when the initializer is a braced-init-list or when it is a
+ // defined when the initializer is a braced-init-list or when it is a
// parenthesized list of expressions.
QualType DestType = Entity.getType();
@@ -3045,6 +3076,10 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (Args[I]->getObjectKind() == OK_ObjCProperty)
+ S.ConvertPropertyForRValue(Args[I]);
+
QualType SourceType;
Expr *Initializer = 0;
if (NumArgs == 1) {
@@ -3052,14 +3087,14 @@ InitializationSequence::InitializationSequence(Sema &S,
if (!isa<InitListExpr>(Initializer))
SourceType = Initializer->getType();
}
-
- // - If the initializer is a braced-init-list, the object is
+
+ // - If the initializer is a braced-init-list, the object is
// list-initialized (8.5.4).
if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
TryListInitialization(S, Entity, Kind, InitList, *this);
return;
}
-
+
// - If the destination type is a reference type, see 8.5.3.
if (DestType->isReferenceType()) {
// C++0x [dcl.init.ref]p1:
@@ -3073,36 +3108,36 @@ InitializationSequence::InitializationSequence(Sema &S,
TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
return;
}
-
- // - If the destination type is an array of characters, an array of
- // char16_t, an array of char32_t, or an array of wchar_t, and the
+
+ // - If the destination type is an array of characters, an array of
+ // char16_t, an array of char32_t, or an array of wchar_t, and the
// initializer is a string literal, see 8.5.2.
if (Initializer && IsStringInit(Initializer, DestType, Context)) {
TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
return;
}
-
+
// - If the initializer is (), the object is value-initialized.
if (Kind.getKind() == InitializationKind::IK_Value ||
(Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
TryValueInitialization(S, Entity, Kind, *this);
return;
}
-
+
// Handle default initialization.
- if (Kind.getKind() == InitializationKind::IK_Default){
+ if (Kind.getKind() == InitializationKind::IK_Default) {
TryDefaultInitialization(S, Entity, Kind, *this);
return;
}
- // - Otherwise, if the destination type is an array, the program is
+ // - Otherwise, if the destination type is an array, the program is
// ill-formed.
if (const ArrayType *AT = Context.getAsArrayType(DestType)) {
if (AT->getElementType()->isAnyCharacterType())
SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
else
SetFailed(FK_ArrayNeedsInitList);
-
+
return;
}
@@ -3112,22 +3147,22 @@ InitializationSequence::InitializationSequence(Sema &S,
AddCAssignmentStep(DestType);
return;
}
-
+
// - If the destination type is a (possibly cv-qualified) class type:
if (DestType->isRecordType()) {
- // - 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
+ // - If the initialization is direct-initialization, or if it is
+ // copy-initialization where the cv-unqualified version of the
+ // source type is the same class as, or a derived class of, the
// class of the destination, constructors are considered. [...]
if (Kind.getKind() == InitializationKind::IK_Direct ||
(Kind.getKind() == InitializationKind::IK_Copy &&
(Context.hasSameUnqualifiedType(SourceType, DestType) ||
S.IsDerivedFrom(SourceType, DestType))))
- TryConstructorInitialization(S, Entity, Kind, Args, NumArgs,
+ TryConstructorInitialization(S, Entity, Kind, Args, NumArgs,
Entity.getType(), *this);
- // - Otherwise (i.e., for the remaining copy-initialization cases),
+ // - 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
+ // 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).
@@ -3135,30 +3170,39 @@ InitializationSequence::InitializationSequence(Sema &S,
TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
return;
}
-
+
if (NumArgs > 1) {
SetFailed(FK_TooManyInitsForScalar);
return;
}
assert(NumArgs == 1 && "Zero-argument case handled above");
-
- // - Otherwise, if the source type is a (possibly cv-qualified) class
+
+ // - Otherwise, if the source type is a (possibly cv-qualified) class
// type, conversion functions are considered.
if (!SourceType.isNull() && SourceType->isRecordType()) {
TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
return;
}
-
+
// - Otherwise, the initial value of the object being initialized is the
// (possibly converted) value of the initializer expression. Standard
// conversions (Clause 4) will be used, if necessary, to convert the
- // initializer expression to the cv-unqualified version of the
+ // initializer expression to the cv-unqualified version of the
// destination type; no user-defined conversions are considered.
if (S.TryImplicitConversion(*this, Entity, Initializer,
/*SuppressUserConversions*/ true,
/*AllowExplicitConversions*/ false,
- /*InOverloadResolution*/ false))
- SetFailed(InitializationSequence::FK_ConversionFailed);
+ /*InOverloadResolution*/ false,
+ /*CStyle=*/Kind.isCStyleOrFunctionalCast()))
+ {
+ DeclAccessPair dap;
+ if (Initializer->getType() == Context.OverloadTy &&
+ !S.ResolveAddressOfOverloadedFunction(Initializer
+ , DestType, false, dap))
+ SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ else
+ SetFailed(InitializationSequence::FK_ConversionFailed);
+ }
else
setSequenceKind(StandardConversion);
}
@@ -3173,15 +3217,17 @@ InitializationSequence::~InitializationSequence() {
//===----------------------------------------------------------------------===//
// Perform initialization
//===----------------------------------------------------------------------===//
-static Sema::AssignmentAction
+static Sema::AssignmentAction
getAssignmentAction(const InitializedEntity &Entity) {
switch(Entity.getKind()) {
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_New:
+ case InitializedEntity::EK_Exception:
+ case InitializedEntity::EK_Base:
return Sema::AA_Initializing;
case InitializedEntity::EK_Parameter:
- if (Entity.getDecl() &&
+ if (Entity.getDecl() &&
isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext()))
return Sema::AA_Sending;
@@ -3190,15 +3236,10 @@ getAssignmentAction(const InitializedEntity &Entity) {
case InitializedEntity::EK_Result:
return Sema::AA_Returning;
- case InitializedEntity::EK_Exception:
- case InitializedEntity::EK_Base:
- llvm_unreachable("No assignment action for C++-specific initialization");
- break;
-
case InitializedEntity::EK_Temporary:
// FIXME: Can we tell apart casting vs. converting?
return Sema::AA_Casting;
-
+
case InitializedEntity::EK_Member:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_VectorElement:
@@ -3223,12 +3264,12 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_BlockElement:
return false;
-
+
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Temporary:
return true;
}
-
+
llvm_unreachable("missed an InitializedEntity kind?");
}
@@ -3243,7 +3284,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_BlockElement:
return false;
-
+
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Temporary:
@@ -3251,8 +3292,8 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
case InitializedEntity::EK_Exception:
return true;
}
-
- llvm_unreachable("missed an InitializedEntity kind?");
+
+ llvm_unreachable("missed an InitializedEntity kind?");
}
/// \brief Make a (potentially elidable) temporary copy of the object
@@ -3261,7 +3302,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
///
/// \param S The Sema object used for type-checking.
///
-/// \param T The type of the temporary object, which must either by
+/// \param T The type of the temporary object, which must either be
/// the type of the initializer expression or a superclass thereof.
///
/// \param Enter The entity being initialized.
@@ -3276,19 +3317,19 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
/// a temporary object, or an error expression if a copy could not be
/// created.
static ExprResult CopyObject(Sema &S,
- QualType T,
- const InitializedEntity &Entity,
- ExprResult CurInit,
- bool IsExtraneousCopy) {
+ QualType T,
+ const InitializedEntity &Entity,
+ ExprResult CurInit,
+ bool IsExtraneousCopy) {
// Determine which class type we're copying to.
Expr *CurInitExpr = (Expr *)CurInit.get();
- CXXRecordDecl *Class = 0;
+ CXXRecordDecl *Class = 0;
if (const RecordType *Record = T->getAs<RecordType>())
Class = cast<CXXRecordDecl>(Record->getDecl());
if (!Class)
return move(CurInit);
- // C++0x [class.copy]p34:
+ // C++0x [class.copy]p32:
// When certain criteria are met, an implementation is allowed to
// omit the copy/move construction of a class object, even if the
// copy/move constructor and/or destructor for the object have
@@ -3298,23 +3339,22 @@ static ExprResult CopyObject(Sema &S,
// with the same cv-unqualified type, the copy/move operation
// can be omitted by constructing the temporary object
// directly into the target of the omitted copy/move
- //
+ //
// Note that the other three bullets are handled elsewhere. Copy
// elision for return statements and throw expressions are handled as part
- // of constructor initialization, while copy elision for exception handlers
+ // of constructor initialization, while copy elision for exception handlers
// is handled by the run-time.
- bool Elidable = CurInitExpr->isTemporaryObject() &&
- S.Context.hasSameUnqualifiedType(T, CurInitExpr->getType());
+ bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class);
SourceLocation Loc;
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
Loc = Entity.getReturnLoc();
break;
-
+
case InitializedEntity::EK_Exception:
Loc = Entity.getThrowLoc();
break;
-
+
case InitializedEntity::EK_Variable:
Loc = Entity.getDecl()->getLocation();
break;
@@ -3331,33 +3371,57 @@ static ExprResult CopyObject(Sema &S,
break;
}
- // Make sure that the type we are copying is complete.
+ // Make sure that the type we are copying is complete.
if (S.RequireCompleteType(Loc, T, S.PDiag(diag::err_temp_copy_incomplete)))
return move(CurInit);
- // Perform overload resolution using the class's copy constructors.
+ // Perform overload resolution using the class's copy/move constructors.
DeclContext::lookup_iterator Con, ConEnd;
OverloadCandidateSet CandidateSet(Loc);
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
Con != ConEnd; ++Con) {
- // Only consider copy constructors.
- CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con);
- if (!Constructor || Constructor->isInvalidDecl() ||
- !Constructor->isCopyConstructor() ||
- !Constructor->isConvertingConstructor(/*AllowExplicit=*/false))
+ // Only consider copy/move constructors and constructor templates. Per
+ // C++0x [dcl.init]p16, second bullet to class types, this
+ // initialization is direct-initialization.
+ CXXConstructorDecl *Constructor = 0;
+
+ if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) {
+ // Handle copy/moveconstructors, only.
+ if (!Constructor || Constructor->isInvalidDecl() ||
+ !Constructor->isCopyOrMoveConstructor() ||
+ !Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
+ continue;
+
+ DeclAccessPair FoundDecl
+ = DeclAccessPair::make(Constructor, Constructor->getAccess());
+ S.AddOverloadCandidate(Constructor, FoundDecl,
+ &CurInitExpr, 1, CandidateSet);
+ continue;
+ }
+
+ // Handle constructor templates.
+ FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con);
+ if (ConstructorTmpl->isInvalidDecl())
+ continue;
+
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
continue;
+ // FIXME: Do we need to limit this to copy-constructor-like
+ // candidates?
DeclAccessPair FoundDecl
- = DeclAccessPair::make(Constructor, Constructor->getAccess());
- S.AddOverloadCandidate(Constructor, FoundDecl,
- &CurInitExpr, 1, CandidateSet);
+ = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0,
+ &CurInitExpr, 1, CandidateSet, true);
}
-
+
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, Loc, Best)) {
case OR_Success:
break;
-
+
case OR_No_Viable_Function:
S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext()
? diag::ext_rvalue_to_reference_temp_copy_no_viable
@@ -3368,14 +3432,14 @@ static ExprResult CopyObject(Sema &S,
if (!IsExtraneousCopy || S.isSFINAEContext())
return ExprError();
return move(CurInit);
-
+
case OR_Ambiguous:
S.Diag(Loc, diag::err_temp_copy_ambiguous)
<< (int)Entity.getKind() << CurInitExpr->getType()
<< CurInitExpr->getSourceRange();
CandidateSet.NoteCandidates(S, OCD_ViableCandidates, &CurInitExpr, 1);
return ExprError();
-
+
case OR_Deleted:
S.Diag(Loc, diag::err_temp_copy_deleted)
<< (int)Entity.getKind() << CurInitExpr->getType()
@@ -3417,7 +3481,7 @@ static ExprResult CopyObject(Sema &S,
return S.Owned(CurInitExpr);
}
-
+
// Determine the arguments required to actually perform the
// constructor call (we might have derived-to-base conversions, or
// the copy constructor may have default arguments).
@@ -3429,8 +3493,9 @@ static ExprResult CopyObject(Sema &S,
CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
move_arg(ConstructorArgs),
/*ZeroInit*/ false,
- CXXConstructExpr::CK_Complete);
-
+ CXXConstructExpr::CK_Complete,
+ SourceRange());
+
// If we're supposed to bind temporaries, do so.
if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
@@ -3451,7 +3516,7 @@ void InitializationSequence::PrintInitLocationNote(Sema &S,
}
}
-ExprResult
+ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -3462,7 +3527,7 @@ InitializationSequence::Perform(Sema &S,
Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
return ExprError();
}
-
+
if (SequenceKind == DependentSequence) {
// If the declaration is a non-dependent, incomplete array type
// that has an initializer, then its type will be completed once
@@ -3512,14 +3577,14 @@ InitializationSequence::Perform(Sema &S,
unsigned NumArgs = Args.size();
return S.Owned(new (S.Context) ParenListExpr(S.Context,
SourceLocation(),
- (Expr **)Args.release(),
+ (Expr **)Args.release(),
NumArgs,
SourceLocation()));
}
if (SequenceKind == NoInitialization)
return S.Owned((Expr *)0);
-
+
QualType DestType = Entity.getType().getNonReferenceType();
// FIXME: Ugly hack around the fact that Entity.getType() is not
// the same as Entity.getDecl()->getType() in cases involving type merging,
@@ -3529,10 +3594,10 @@ InitializationSequence::Perform(Sema &S,
Entity.getType();
ExprResult CurInit = S.Owned((Expr *)0);
-
+
assert(!Steps.empty() && "Cannot have an empty initialization sequence");
-
- // For initialization steps that start with a single initializer,
+
+ // For initialization steps that start with a single initializer,
// grab the only argument out the Args and place it into the "current"
// initializer.
switch (Steps.front().Kind) {
@@ -3551,32 +3616,38 @@ InitializationSequence::Perform(Sema &S,
case SK_ListInitialization:
case SK_CAssignment:
case SK_StringInit:
- case SK_ObjCObjectConversion:
+ case SK_ObjCObjectConversion: {
assert(Args.size() == 1);
- CurInit = ExprResult(((Expr **)(Args.get()))[0]->Retain());
- if (CurInit.isInvalid())
- return ExprError();
+ Expr *CurInitExpr = Args.get()[0];
+ if (!CurInitExpr) return ExprError();
+
+ // Read from a property when initializing something with it.
+ if (CurInitExpr->getObjectKind() == OK_ObjCProperty)
+ S.ConvertPropertyForRValue(CurInitExpr);
+
+ CurInit = ExprResult(CurInitExpr);
break;
-
+ }
+
case SK_ConstructorInitialization:
case SK_ZeroInitialization:
break;
}
-
- // Walk through the computed steps for the initialization sequence,
+
+ // Walk through the computed steps for the initialization sequence,
// performing the specified conversions along the way.
bool ConstructorInitRequiresZeroInit = false;
for (step_iterator Step = step_begin(), StepEnd = step_end();
Step != StepEnd; ++Step) {
if (CurInit.isInvalid())
return ExprError();
-
- Expr *CurInitExpr = (Expr *)CurInit.get();
+
+ Expr *CurInitExpr = CurInit.get();
QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType();
-
+
switch (Step->Kind) {
case SK_ResolveAddressOfOverloadedFunction:
- // Overload resolution determined which function invoke; update the
+ // Overload resolution determined which function invoke; update the
// initializer to reflect that choice.
S.CheckAddressOfMemberAccess(CurInitExpr, Step->Function.FoundDecl);
S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation());
@@ -3584,29 +3655,29 @@ InitializationSequence::Perform(Sema &S,
Step->Function.FoundDecl,
Step->Function.Function);
break;
-
+
case SK_CastDerivedToBaseRValue:
case SK_CastDerivedToBaseXValue:
case SK_CastDerivedToBaseLValue: {
// We have a derived-to-base cast that produces either an rvalue or an
// lvalue. Perform that cast.
-
+
CXXCastPath BasePath;
// Casts to inaccessible base classes are allowed with C-style casts.
bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
if (S.CheckDerivedToBaseConversion(SourceType, Step->Type,
CurInitExpr->getLocStart(),
- CurInitExpr->getSourceRange(),
+ CurInitExpr->getSourceRange(),
&BasePath, IgnoreBaseAccess))
return ExprError();
-
+
if (S.BasePathInvolvesVirtualBase(BasePath)) {
QualType T = SourceType;
if (const PointerType *Pointer = T->getAs<PointerType>())
T = Pointer->getPointeeType();
if (const RecordType *RecordTy = T->getAs<RecordType>())
- S.MarkVTableUsed(CurInitExpr->getLocStart(),
+ S.MarkVTableUsed(CurInitExpr->getLocStart(),
cast<CXXRecordDecl>(RecordTy->getDecl()));
}
@@ -3623,7 +3694,7 @@ InitializationSequence::Perform(Sema &S,
&BasePath, VK));
break;
}
-
+
case SK_BindReference:
if (FieldDecl *BitField = CurInitExpr->getBitField()) {
// References cannot bind to bit fields (C++ [dcl.init.ref]p5).
@@ -3643,7 +3714,7 @@ InitializationSequence::Perform(Sema &S,
PrintInitLocationNote(S, Entity);
return ExprError();
}
-
+
// Reference binding does not have any corresponding ASTs.
// Check exception specifications
@@ -3660,16 +3731,16 @@ InitializationSequence::Perform(Sema &S,
return ExprError();
break;
-
+
case SK_ExtraneousCopyToTemporary:
- CurInit = CopyObject(S, Step->Type, Entity, move(CurInit),
+ CurInit = CopyObject(S, Step->Type, Entity, move(CurInit),
/*IsExtraneousCopy=*/true);
break;
case SK_UserConversion: {
// We have a user-defined conversion that invokes either a constructor
// or a conversion function.
- CastKind CastKind = CK_Unknown;
+ CastKind CastKind;
bool IsCopy = false;
FunctionDecl *Fn = Step->Function.Function;
DeclAccessPair FoundFn = Step->Function.FoundDecl;
@@ -3687,25 +3758,26 @@ InitializationSequence::Perform(Sema &S,
MultiExprArg(&CurInitExpr, 1),
Loc, ConstructorArgs))
return ExprError();
-
+
// Build the an expression that constructs a temporary.
- CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
+ CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
move_arg(ConstructorArgs),
/*ZeroInit*/ false,
- CXXConstructExpr::CK_Complete);
+ CXXConstructExpr::CK_Complete,
+ SourceRange());
if (CurInit.isInvalid())
return ExprError();
S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
FoundFn.getAccess());
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
-
+
CastKind = CK_ConstructorConversion;
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
S.IsDerivedFrom(SourceType, Class))
IsCopy = true;
-
+
CreatedObject = true;
} else {
// Build a call to the conversion function.
@@ -3714,8 +3786,8 @@ InitializationSequence::Perform(Sema &S,
S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, 0,
FoundFn);
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
-
- // FIXME: Should we move this initialization into a separate
+
+ // FIXME: Should we move this initialization into a separate
// derived-to-base conversion? I believe the answer is "no", because
// we don't want to turn off access control here for c-style casts.
if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0,
@@ -3725,19 +3797,18 @@ InitializationSequence::Perform(Sema &S,
// Do a little dance to make sure that CurInit has the proper
// pointer.
CurInit.release();
-
+
// Build the actual call to the conversion function.
- CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn,
- Conversion));
+ CurInit = S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn, Conversion);
if (CurInit.isInvalid() || !CurInit.get())
return ExprError();
-
+
CastKind = CK_UserDefinedConversion;
-
+
CreatedObject = Conversion->getResultType()->isRecordType();
}
-
- bool RequiresCopy = !IsCopy &&
+
+ bool RequiresCopy = !IsCopy &&
getKind() != InitializationSequence::ReferenceBinding;
if (RequiresCopy || shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
@@ -3745,21 +3816,22 @@ InitializationSequence::Perform(Sema &S,
CurInitExpr = static_cast<Expr *>(CurInit.get());
QualType T = CurInitExpr->getType();
if (const RecordType *Record = T->getAs<RecordType>()) {
- CXXDestructorDecl *Destructor
+ CXXDestructorDecl *Destructor
= S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
- S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor,
+ S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << T);
S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor);
+ S.DiagnoseUseOfDecl(Destructor, CurInitExpr->getLocStart());
}
}
-
+
CurInitExpr = CurInit.takeAs<Expr>();
// FIXME: xvalues
CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
CurInitExpr->getType(),
CastKind, CurInitExpr, 0,
IsLvalue ? VK_LValue : VK_RValue));
-
+
if (RequiresCopy)
CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
move(CurInit), /*IsExtraneousCopy=*/false);
@@ -3784,17 +3856,16 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ConversionSequence: {
- bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
-
if (S.PerformImplicitConversion(CurInitExpr, Step->Type, *Step->ICS,
- Sema::AA_Converting, IgnoreBaseAccess))
+ getAssignmentAction(Entity),
+ Kind.isCStyleOrFunctionalCast()))
return ExprError();
-
+
CurInit.release();
CurInit = S.Owned(CurInitExpr);
break;
}
-
+
case SK_ListInitialization: {
InitListExpr *InitList = cast<InitListExpr>(CurInitExpr);
QualType Ty = Step->Type;
@@ -3810,7 +3881,7 @@ InitializationSequence::Perform(Sema &S,
unsigned NumArgs = Args.size();
CXXConstructorDecl *Constructor
= cast<CXXConstructorDecl>(Step->Function.Function);
-
+
// Build a call to the selected constructor.
ASTOwningVector<Expr*> ConstructorArgs(S);
SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
@@ -3830,11 +3901,11 @@ InitializationSequence::Perform(Sema &S,
// Determine the arguments required to actually perform the constructor
// call.
- if (S.CompleteConstructorCall(Constructor, move(Args),
+ if (S.CompleteConstructorCall(Constructor, move(Args),
Loc, ConstructorArgs))
return ExprError();
-
-
+
+
if (Entity.getKind() == InitializedEntity::EK_Temporary &&
NumArgs != 1 && // FIXME: Hack to work around cast weirdness
(Kind.getKind() == InitializationKind::IK_Direct ||
@@ -3843,24 +3914,34 @@ InitializationSequence::Perform(Sema &S,
unsigned NumExprs = ConstructorArgs.size();
Expr **Exprs = (Expr **)ConstructorArgs.take();
S.MarkDeclarationReferenced(Loc, Constructor);
+ S.DiagnoseUseOfDecl(Constructor, Loc);
+
+ TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
+ if (!TSInfo)
+ TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
+
CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
Constructor,
- Entity.getType(),
- Loc,
- Exprs,
+ TSInfo,
+ Exprs,
NumExprs,
- Kind.getParenRange().getEnd(),
+ Kind.getParenRange(),
ConstructorInitRequiresZeroInit));
} else {
CXXConstructExpr::ConstructionKind ConstructKind =
CXXConstructExpr::CK_Complete;
-
+
if (Entity.getKind() == InitializedEntity::EK_Base) {
ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
- CXXConstructExpr::CK_VirtualBase :
+ CXXConstructExpr::CK_VirtualBase :
CXXConstructExpr::CK_NonVirtualBase;
- }
-
+ }
+
+ // Only get the parenthesis range if it is a direct construction.
+ SourceRange parenRange =
+ Kind.getKind() == InitializationKind::IK_Direct ?
+ Kind.getParenRange() : SourceRange();
+
// If the entity allows NRVO, mark the construction as elidable
// unconditionally.
if (Entity.allowsNRVO())
@@ -3868,13 +3949,15 @@ InitializationSequence::Perform(Sema &S,
Constructor, /*Elidable=*/true,
move_arg(ConstructorArgs),
ConstructorInitRequiresZeroInit,
- ConstructKind);
+ ConstructKind,
+ parenRange);
else
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
- Constructor,
+ Constructor,
move_arg(ConstructorArgs),
ConstructorInitRequiresZeroInit,
- ConstructKind);
+ ConstructKind,
+ parenRange);
}
if (CurInit.isInvalid())
return ExprError();
@@ -3883,17 +3966,17 @@ InitializationSequence::Perform(Sema &S,
S.CheckConstructorAccess(Loc, Constructor, Entity,
Step->Function.FoundDecl.getAccess());
S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Loc);
-
+
if (shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
-
+
break;
}
-
+
case SK_ZeroInitialization: {
step_iterator NextStep = Step;
++NextStep;
- if (NextStep != StepEnd &&
+ if (NextStep != StepEnd &&
NextStep->Kind == SK_ConstructorInitialization) {
// The need for zero-initialization is recorded directly into
// the call to the object's constructor within the next step.
@@ -3901,8 +3984,14 @@ InitializationSequence::Perform(Sema &S,
} else if (Kind.getKind() == InitializationKind::IK_Value &&
S.getLangOptions().CPlusPlus &&
!Kind.isImplicitValueInit()) {
- CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr(Step->Type,
- Kind.getRange().getBegin(),
+ TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
+ if (!TSInfo)
+ TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type,
+ Kind.getRange().getBegin());
+
+ CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr(
+ TSInfo->getType().getNonLValueExprType(S.Context),
+ TSInfo,
Kind.getRange().getEnd()));
} else {
CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type));
@@ -3925,7 +4014,7 @@ InitializationSequence::Perform(Sema &S,
bool Complained;
if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
Step->Type, SourceType,
- CurInitExpr,
+ CurInitExpr,
getAssignmentAction(Entity),
&Complained)) {
PrintInitLocationNote(S, Entity);
@@ -3945,7 +4034,7 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ObjCObjectConversion:
- S.ImpCastExprToType(CurInitExpr, Step->Type,
+ S.ImpCastExprToType(CurInitExpr, Step->Type,
CK_ObjCObjectLValueCast,
S.CastCategory(CurInitExpr));
CurInit.release();
@@ -3953,20 +4042,27 @@ InitializationSequence::Perform(Sema &S,
break;
}
}
-
+
+ // Diagnose non-fatal problems with the completed initialization.
+ if (Entity.getKind() == InitializedEntity::EK_Member &&
+ cast<FieldDecl>(Entity.getDecl())->isBitField())
+ S.CheckBitFieldInitialization(Kind.getLocation(),
+ cast<FieldDecl>(Entity.getDecl()),
+ CurInit.get());
+
return move(CurInit);
}
//===----------------------------------------------------------------------===//
// Diagnose initialization failures
//===----------------------------------------------------------------------===//
-bool InitializationSequence::Diagnose(Sema &S,
+bool InitializationSequence::Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Expr **Args, unsigned NumArgs) {
if (SequenceKind != FailedSequence)
return false;
-
+
QualType DestType = Entity.getType();
switch (Failure) {
case FK_TooManyInitsForReference:
@@ -3978,22 +4074,22 @@ bool InitializationSequence::Diagnose(Sema &S,
S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
<< SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
break;
-
+
case FK_ArrayNeedsInitList:
case FK_ArrayNeedsInitListOrStringLiteral:
S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list)
<< (Failure == FK_ArrayNeedsInitListOrStringLiteral);
break;
-
+
case FK_AddressOfOverloadFailed: {
DeclAccessPair Found;
- S.ResolveAddressOfOverloadedFunction(Args[0],
+ S.ResolveAddressOfOverloadedFunction(Args[0],
DestType.getNonReferenceType(),
true,
Found);
break;
}
-
+
case FK_ReferenceInitOverloadFailed:
case FK_UserConversionOverloadFailed:
switch (FailedOverloadResult) {
@@ -4009,21 +4105,22 @@ bool InitializationSequence::Diagnose(Sema &S,
FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args, NumArgs);
break;
-
+
case OR_No_Viable_Function:
S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
<< Args[0]->getType() << DestType.getNonReferenceType()
<< Args[0]->getSourceRange();
FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs);
break;
-
+
case OR_Deleted: {
S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
<< Args[0]->getType() << DestType.getNonReferenceType()
<< Args[0]->getSourceRange();
OverloadCandidateSet::iterator Best;
OverloadingResult Ovl
- = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
+ = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best,
+ true);
if (Ovl == OR_Deleted) {
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
<< Best->Function->isDeleted();
@@ -4032,16 +4129,16 @@ bool InitializationSequence::Diagnose(Sema &S,
}
break;
}
-
+
case OR_Success:
llvm_unreachable("Conversion did not fail!");
break;
}
break;
-
+
case FK_NonConstLValueReferenceBindingToTemporary:
case FK_NonConstLValueReferenceBindingToUnrelated:
- S.Diag(Kind.getLocation(),
+ S.Diag(Kind.getLocation(),
Failure == FK_NonConstLValueReferenceBindingToTemporary
? diag::err_lvalue_reference_bind_to_temporary
: diag::err_lvalue_reference_bind_to_unrelated)
@@ -4050,47 +4147,54 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getType()
<< Args[0]->getSourceRange();
break;
-
+
case FK_RValueReferenceBindingToLValue:
S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
+ << DestType.getNonReferenceType() << Args[0]->getType()
<< Args[0]->getSourceRange();
break;
-
+
case FK_ReferenceInitDropsQualifiers:
S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
<< DestType.getNonReferenceType()
<< Args[0]->getType()
<< Args[0]->getSourceRange();
break;
-
+
case FK_ReferenceInitFailed:
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
<< DestType.getNonReferenceType()
- << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
+ << Args[0]->isLValue()
<< Args[0]->getType()
<< Args[0]->getSourceRange();
break;
-
- case FK_ConversionFailed:
+
+ case FK_ConversionFailed: {
+ QualType FromType = Args[0]->getType();
S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
<< (int)Entity.getKind()
<< DestType
- << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
- << Args[0]->getType()
+ << Args[0]->isLValue()
+ << FromType
<< Args[0]->getSourceRange();
break;
-
+ }
case FK_TooManyInitsForScalar: {
SourceRange R;
if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0]))
- R = SourceRange(InitList->getInit(1)->getLocStart(),
+ R = SourceRange(InitList->getInit(0)->getLocEnd(),
InitList->getLocEnd());
else
- R = SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+ R = SourceRange(Args[0]->getLocEnd(), Args[NumArgs - 1]->getLocEnd());
- S.Diag(Kind.getLocation(), diag::err_excess_initializers)
- << /*scalar=*/2 << R;
+ R.setBegin(S.PP.getLocForEndOfToken(R.getBegin()));
+ if (Kind.isCStyleOrFunctionalCast())
+ S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
+ << R;
+ else
+ S.Diag(Kind.getLocation(), diag::err_excess_initializers)
+ << /*scalar=*/2 << R;
break;
}
@@ -4103,13 +4207,13 @@ bool InitializationSequence::Diagnose(Sema &S,
S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
<< (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
break;
-
+
case FK_ConstructorOverloadFailed: {
SourceRange ArgsRange;
if (NumArgs)
- ArgsRange = SourceRange(Args[0]->getLocStart(),
+ ArgsRange = SourceRange(Args[0]->getLocStart(),
Args[NumArgs - 1]->getLocEnd());
-
+
// FIXME: Using "DestType" for the entity we're printing is probably
// bad.
switch (FailedOverloadResult) {
@@ -4119,7 +4223,7 @@ bool InitializationSequence::Diagnose(Sema &S,
FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates,
Args, NumArgs);
break;
-
+
case OR_No_Viable_Function:
if (Kind.getKind() == InitializationKind::IK_Default &&
(Entity.getKind() == InitializedEntity::EK_Base ||
@@ -4153,7 +4257,7 @@ bool InitializationSequence::Diagnose(Sema &S,
if (const RecordType *Record
= Entity.getType()->getAs<RecordType>())
- S.Diag(Record->getDecl()->getLocation(),
+ S.Diag(Record->getDecl()->getLocation(),
diag::note_previous_decl)
<< S.Context.getTagDeclType(Record->getDecl());
}
@@ -4164,7 +4268,7 @@ bool InitializationSequence::Diagnose(Sema &S,
<< DestType << ArgsRange;
FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs);
break;
-
+
case OR_Deleted: {
S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
<< true << DestType << ArgsRange;
@@ -4179,14 +4283,14 @@ bool InitializationSequence::Diagnose(Sema &S,
}
break;
}
-
+
case OR_Success:
llvm_unreachable("Conversion did not fail!");
break;
}
break;
}
-
+
case FK_DefaultInitOfConst:
if (Entity.getKind() == InitializedEntity::EK_Member &&
isa<CXXConstructorDecl>(S.CurContext)) {
@@ -4206,13 +4310,13 @@ bool InitializationSequence::Diagnose(Sema &S,
<< DestType << (bool)DestType->getAs<RecordType>();
}
break;
-
+
case FK_Incomplete:
- S.RequireCompleteType(Kind.getLocation(), DestType,
+ S.RequireCompleteType(Kind.getLocation(), DestType,
diag::err_init_incomplete_type);
- break;
+ break;
}
-
+
PrintInitLocationNote(S, Entity);
return true;
}
@@ -4225,95 +4329,95 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case FK_TooManyInitsForReference:
OS << "too many initializers for reference";
break;
-
+
case FK_ArrayNeedsInitList:
OS << "array requires initializer list";
break;
-
+
case FK_ArrayNeedsInitListOrStringLiteral:
OS << "array requires initializer list or string literal";
break;
-
+
case FK_AddressOfOverloadFailed:
OS << "address of overloaded function failed";
break;
-
+
case FK_ReferenceInitOverloadFailed:
OS << "overload resolution for reference initialization failed";
break;
-
+
case FK_NonConstLValueReferenceBindingToTemporary:
OS << "non-const lvalue reference bound to temporary";
break;
-
+
case FK_NonConstLValueReferenceBindingToUnrelated:
OS << "non-const lvalue reference bound to unrelated type";
break;
-
+
case FK_RValueReferenceBindingToLValue:
OS << "rvalue reference bound to an lvalue";
break;
-
+
case FK_ReferenceInitDropsQualifiers:
OS << "reference initialization drops qualifiers";
break;
-
+
case FK_ReferenceInitFailed:
OS << "reference initialization failed";
break;
-
+
case FK_ConversionFailed:
OS << "conversion failed";
break;
-
+
case FK_TooManyInitsForScalar:
OS << "too many initializers for scalar";
break;
-
+
case FK_ReferenceBindingToInitList:
OS << "referencing binding to initializer list";
break;
-
+
case FK_InitListBadDestinationType:
OS << "initializer list for non-aggregate, non-scalar type";
break;
-
+
case FK_UserConversionOverloadFailed:
OS << "overloading failed for user-defined conversion";
break;
-
+
case FK_ConstructorOverloadFailed:
OS << "constructor overloading failed";
break;
-
+
case FK_DefaultInitOfConst:
OS << "default initialization of a const variable";
break;
-
+
case FK_Incomplete:
OS << "initialization of incomplete type";
break;
- }
+ }
OS << '\n';
return;
}
-
+
case DependentSequence:
OS << "Dependent sequence: ";
return;
-
+
case UserDefinedConversion:
OS << "User-defined conversion sequence: ";
break;
-
+
case ConstructorInitialization:
OS << "Constructor initialization sequence: ";
break;
-
+
case ReferenceBinding:
OS << "Reference binding: ";
break;
-
+
case ListInitialization:
OS << "List initialization: ";
break;
@@ -4321,54 +4425,54 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case ZeroInitialization:
OS << "Zero initialization\n";
return;
-
+
case NoInitialization:
OS << "No initialization\n";
return;
-
+
case StandardConversion:
OS << "Standard conversion: ";
break;
-
+
case CAssignment:
OS << "C assignment: ";
break;
-
+
case StringInit:
OS << "String initialization: ";
break;
}
-
+
for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
if (S != step_begin()) {
OS << " -> ";
}
-
+
switch (S->Kind) {
case SK_ResolveAddressOfOverloadedFunction:
OS << "resolve address of overloaded function";
break;
-
+
case SK_CastDerivedToBaseRValue:
OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
break;
-
+
case SK_CastDerivedToBaseXValue:
OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")";
break;
-
+
case SK_CastDerivedToBaseLValue:
OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
break;
-
+
case SK_BindReference:
OS << "bind reference to lvalue";
break;
-
+
case SK_BindReferenceToTemporary:
OS << "bind reference to a temporary";
break;
-
+
case SK_ExtraneousCopyToTemporary:
OS << "extraneous C++03 copy to temporary";
break;
@@ -4386,29 +4490,29 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case SK_QualificationConversionLValue:
OS << "qualification conversion (lvalue)";
break;
-
+
case SK_ConversionSequence:
OS << "implicit conversion sequence (";
S->ICS->DebugPrint(); // FIXME: use OS
OS << ")";
break;
-
+
case SK_ListInitialization:
OS << "list initialization";
break;
-
+
case SK_ConstructorInitialization:
OS << "constructor initialization";
break;
-
+
case SK_ZeroInitialization:
OS << "zero initialization";
break;
-
+
case SK_CAssignment:
OS << "C assignment";
break;
-
+
case SK_StringInit:
OS << "string initialization";
break;
@@ -4427,14 +4531,14 @@ void InitializationSequence::dump() const {
//===----------------------------------------------------------------------===//
// Initialization helper functions
//===----------------------------------------------------------------------===//
-ExprResult
+ExprResult
Sema::PerformCopyInitialization(const InitializedEntity &Entity,
SourceLocation EqualLoc,
ExprResult Init) {
if (Init.isInvalid())
return ExprError();
- Expr *InitE = (Expr *)Init.get();
+ Expr *InitE = Init.get();
assert(InitE && "No initialization expression?");
if (EqualLoc.isInvalid())
OpenPOWER on IntegriCloud