diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-01-01 10:34:51 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-01-01 10:34:51 +0000 |
commit | bb1e3bc1e0be2b8f891db46457a8943451bf4d8b (patch) | |
tree | 1e68501209c9133fbda8d45171e59f8d6f12dd55 /lib/Sema/SemaInit.cpp | |
parent | 77212133072dc40f070a280af8217032f55a9eb4 (diff) | |
download | FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.zip FreeBSD-src-bb1e3bc1e0be2b8f891db46457a8943451bf4d8b.tar.gz |
Updaet clang to 92395.
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 1140 |
1 files changed, 724 insertions, 416 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 4518465..3ef5156 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -16,11 +16,13 @@ //===----------------------------------------------------------------------===// #include "SemaInit.h" +#include "Lookup.h" #include "Sema.h" #include "clang/Parse/Designator.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeLoc.h" #include "llvm/Support/ErrorHandling.h" #include <map> using namespace clang; @@ -73,7 +75,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, if (S.getLangOptions().CPlusPlus) { // FIXME: I dislike this error message. A lot. if (S.PerformImplicitConversion(Init, DeclType, - "initializing", DirectInit)) { + Sema::AA_Initializing, DirectInit)) { ImplicitConversionSequence ICS; OverloadCandidateSet CandidateSet; if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined, @@ -81,7 +83,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, true, false, false) != OR_Ambiguous) return S.Diag(Init->getSourceRange().getBegin(), diag::err_typecheck_convert_incompatible) - << DeclType << Init->getType() << "initializing" + << DeclType << Init->getType() << Sema::AA_Initializing << Init->getSourceRange(); S.Diag(Init->getSourceRange().getBegin(), diag::err_typecheck_convert_ambiguous) @@ -95,7 +97,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(DeclType, Init); return S.DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType, - InitType, Init, "initializing"); + InitType, Init, Sema::AA_Initializing); } static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) { @@ -134,172 +136,6 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) { Str->setType(DeclT); } -bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType, - SourceLocation InitLoc, - DeclarationName InitEntity, bool DirectInit) { - if (DeclType->isDependentType() || - Init->isTypeDependent() || Init->isValueDependent()) { - // We have either a dependent type or a type- or value-dependent - // initializer, so we don't perform any additional checking at - // this point. - - // If the declaration is a non-dependent, incomplete array type - // that has an initializer, then its type will be completed once - // the initializer is instantiated. - if (!DeclType->isDependentType()) { - if (const IncompleteArrayType *ArrayT - = Context.getAsIncompleteArrayType(DeclType)) { - if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { - if (!ILE->isTypeDependent()) { - // Compute the constant array type from the length of the - // initializer list. - // FIXME: This will be wrong if there are designated - // initializations. Good thing they don't exist in C++! - llvm::APInt NumElements(Context.getTypeSize(Context.getSizeType()), - ILE->getNumInits()); - llvm::APInt Zero(Context.getTypeSize(Context.getSizeType()), 0); - if (NumElements == Zero) { - // Sizing an array implicitly to zero is not allowed by ISO C, - // but is supported by GNU. - Diag(ILE->getLocStart(), diag::ext_typecheck_zero_array_size); - } - - DeclType = Context.getConstantArrayType(ArrayT->getElementType(), - NumElements, - ArrayT->getSizeModifier(), - ArrayT->getIndexTypeCVRQualifiers()); - return false; - } - } - - // Make the array type-dependent by making it dependently-sized. - DeclType = Context.getDependentSizedArrayType(ArrayT->getElementType(), - /*NumElts=*/0, - ArrayT->getSizeModifier(), - ArrayT->getIndexTypeCVRQualifiers(), - SourceRange()); - } - } - - return false; - } - - // C++ [dcl.init.ref]p1: - // A variable declared to be a T& or T&&, that is "reference to type T" - // (8.3.2), shall be initialized by an object, or function, of - // type T or by an object that can be converted into a T. - if (DeclType->isReferenceType()) - return CheckReferenceInit(Init, DeclType, InitLoc, - /*SuppressUserConversions=*/false, - /*AllowExplicit=*/DirectInit, - /*ForceRValue=*/false); - - // C99 6.7.8p3: The type of the entity to be initialized shall be an array - // of unknown size ("[]") or an object type that is not a variable array type. - if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType)) - return Diag(InitLoc, diag::err_variable_object_no_init) - << VAT->getSizeExpr()->getSourceRange(); - - InitListExpr *InitList = dyn_cast<InitListExpr>(Init); - if (!InitList) { - // FIXME: Handle wide strings - if (Expr *Str = IsStringInit(Init, DeclType, Context)) { - CheckStringInit(Str, DeclType, *this); - return false; - } - - // C++ [dcl.init]p14: - // -- If the destination type is a (possibly cv-qualified) class - // type: - if (getLangOptions().CPlusPlus && DeclType->isRecordType()) { - QualType DeclTypeC = Context.getCanonicalType(DeclType); - QualType InitTypeC = Context.getCanonicalType(Init->getType()); - - // -- If the initialization is direct-initialization, or if it is - // copy-initialization where the cv-unqualified version of the - // source type is the same class as, or a derived class of, the - // class of the destination, constructors are considered. - if ((DeclTypeC.getLocalUnqualifiedType() - == InitTypeC.getLocalUnqualifiedType()) || - IsDerivedFrom(InitTypeC, DeclTypeC)) { - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(DeclType->getAs<RecordType>()->getDecl()); - - // No need to make a CXXConstructExpr if both the ctor and dtor are - // trivial. - if (RD->hasTrivialConstructor() && RD->hasTrivialDestructor()) - return false; - - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - - // FIXME: Poor location information - InitializationKind InitKind - = InitializationKind::CreateCopy(Init->getLocStart(), - SourceLocation()); - if (DirectInit) - InitKind = InitializationKind::CreateDirect(Init->getLocStart(), - SourceLocation(), - SourceLocation()); - CXXConstructorDecl *Constructor - = PerformInitializationByConstructor(DeclType, - MultiExprArg(*this, - (void **)&Init, 1), - InitLoc, Init->getSourceRange(), - InitEntity, InitKind, - ConstructorArgs); - if (!Constructor) - return true; - - OwningExprResult InitResult = - BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - DeclType, Constructor, - move_arg(ConstructorArgs)); - if (InitResult.isInvalid()) - return true; - - Init = InitResult.takeAs<Expr>(); - return false; - } - - // -- Otherwise (i.e., for the remaining copy-initialization - // cases), user-defined conversion sequences that can - // convert from the source type to the destination type or - // (when a conversion function is used) to a derived class - // thereof are enumerated as described in 13.3.1.4, and the - // best one is chosen through overload resolution - // (13.3). If the conversion cannot be done or is - // ambiguous, the initialization is ill-formed. The - // function selected is called with the initializer - // expression as its argument; if the function is a - // constructor, the call initializes a temporary of the - // destination type. - // FIXME: We're pretending to do copy elision here; return to this when we - // have ASTs for such things. - if (!PerformImplicitConversion(Init, DeclType, "initializing")) - return false; - - if (InitEntity) - return Diag(InitLoc, diag::err_cannot_initialize_decl) - << InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid) - << Init->getType() << Init->getSourceRange(); - return Diag(InitLoc, diag::err_cannot_initialize_decl_noname) - << DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid) - << Init->getType() << Init->getSourceRange(); - } - - // C99 6.7.8p16. - if (DeclType->isArrayType()) - return Diag(Init->getLocStart(), diag::err_array_init_list_required) - << Init->getSourceRange(); - - return CheckSingleInitializer(Init, DeclType, DirectInit, *this); - } - - bool hadError = CheckInitList(InitList, DeclType); - Init = InitList; - return hadError; -} - //===----------------------------------------------------------------------===// // Semantic checking for initializer lists. //===----------------------------------------------------------------------===// @@ -399,9 +235,14 @@ class InitListChecker { int numArrayElements(QualType DeclType); int numStructUnionElements(QualType DeclType); - void FillInValueInitializations(InitListExpr *ILE); + void FillInValueInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, bool &RequiresSecondPass); + void FillInValueInitializations(const InitializedEntity &Entity, + InitListExpr *ILE, bool &RequiresSecondPass); public: - InitListChecker(Sema &S, InitListExpr *IL, QualType &T); + InitListChecker(Sema &S, const InitializedEntity &Entity, + InitListExpr *IL, QualType &T); bool HadError() { return hadError; } // @brief Retrieves the fully-structured initializer list used for @@ -410,10 +251,75 @@ public: }; } // end anonymous namespace +void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, + bool &RequiresSecondPass) { + SourceLocation Loc = ILE->getSourceRange().getBegin(); + unsigned NumInits = ILE->getNumInits(); + InitializedEntity MemberEntity + = InitializedEntity::InitializeMember(Field, &ParentEntity); + if (Init >= NumInits || !ILE->getInit(Init)) { + // FIXME: We probably don't need to handle references + // specially here, since value-initialization of references is + // handled in InitializationSequence. + if (Field->getType()->isReferenceType()) { + // C++ [dcl.init.aggr]p9: + // If an incomplete or empty initializer-list leaves a + // member of reference type uninitialized, the program is + // ill-formed. + SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) + << Field->getType() + << ILE->getSyntacticForm()->getSourceRange(); + SemaRef.Diag(Field->getLocation(), + diag::note_uninit_reference_member); + hadError = true; + return; + } + + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0); + if (!InitSeq) { + InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0); + hadError = true; + return; + } + + Sema::OwningExprResult MemberInit + = InitSeq.Perform(SemaRef, MemberEntity, Kind, + Sema::MultiExprArg(SemaRef, 0, 0)); + if (MemberInit.isInvalid()) { + hadError = true; + return; + } + + if (hadError) { + // Do nothing + } else if (Init < NumInits) { + ILE->setInit(Init, MemberInit.takeAs<Expr>()); + } else if (InitSeq.getKind() + == InitializationSequence::ConstructorInitialization) { + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(Init, MemberInit.takeAs<Expr>()); + RequiresSecondPass = true; + } + } else if (InitListExpr *InnerILE + = dyn_cast<InitListExpr>(ILE->getInit(Init))) + FillInValueInitializations(MemberEntity, InnerILE, + RequiresSecondPass); +} + /// Recursively replaces NULL values within the given initializer list /// with expressions that perform value-initialization of the /// appropriate type. -void InitListChecker::FillInValueInitializations(InitListExpr *ILE) { +void +InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, + InitListExpr *ILE, + bool &RequiresSecondPass) { assert((ILE->getType() != SemaRef.Context.VoidTy) && "Should not have void type"); SourceLocation Loc = ILE->getSourceRange().getBegin(); @@ -421,46 +327,32 @@ void InitListChecker::FillInValueInitializations(InitListExpr *ILE) { Loc = ILE->getSyntacticForm()->getSourceRange().getBegin(); if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) { - unsigned Init = 0, NumInits = ILE->getNumInits(); - for (RecordDecl::field_iterator - Field = RType->getDecl()->field_begin(), - FieldEnd = RType->getDecl()->field_end(); - Field != FieldEnd; ++Field) { - if (Field->isUnnamedBitfield()) - continue; - - if (Init >= NumInits || !ILE->getInit(Init)) { - if (Field->getType()->isReferenceType()) { - // C++ [dcl.init.aggr]p9: - // If an incomplete or empty initializer-list leaves a - // member of reference type uninitialized, the program is - // ill-formed. - SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) - << Field->getType() - << ILE->getSyntacticForm()->getSourceRange(); - SemaRef.Diag(Field->getLocation(), - diag::note_uninit_reference_member); - hadError = true; + if (RType->getDecl()->isUnion() && + ILE->getInitializedFieldInUnion()) + FillInValueInitForField(0, ILE->getInitializedFieldInUnion(), + Entity, ILE, RequiresSecondPass); + else { + unsigned Init = 0; + for (RecordDecl::field_iterator + Field = RType->getDecl()->field_begin(), + FieldEnd = RType->getDecl()->field_end(); + Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + if (hadError) return; - } else if (SemaRef.CheckValueInitialization(Field->getType(), Loc)) { - hadError = true; + + FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass); + if (hadError) return; - } - // FIXME: If value-initialization involves calling a constructor, should - // we make that call explicit in the representation (even when it means - // extending the initializer list)? - if (Init < NumInits && !hadError) - ILE->setInit(Init, - new (SemaRef.Context) ImplicitValueInitExpr(Field->getType())); - } else if (InitListExpr *InnerILE - = dyn_cast<InitListExpr>(ILE->getInit(Init))) - FillInValueInitializations(InnerILE); - ++Init; + ++Init; - // Only look at the first initialization of a union. - if (RType->getDecl()->isUnion()) - break; + // Only look at the first initialization of a union. + if (RType->getDecl()->isUnion()) + break; + } } return; @@ -468,39 +360,71 @@ void InitListChecker::FillInValueInitializations(InitListExpr *ILE) { QualType ElementType; + InitializedEntity ElementEntity = Entity; unsigned NumInits = ILE->getNumInits(); unsigned NumElements = NumInits; if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { ElementType = AType->getElementType(); if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) NumElements = CAType->getSize().getZExtValue(); + 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, + 0, Entity); } else ElementType = ILE->getType(); + for (unsigned Init = 0; Init != NumElements; ++Init) { + if (hadError) + return; + + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayOrVectorElement) + ElementEntity.setElementIndex(Init); + if (Init >= NumInits || !ILE->getInit(Init)) { - if (SemaRef.CheckValueInitialization(ElementType, Loc)) { + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0); + if (!InitSeq) { + InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0); hadError = true; return; } - // FIXME: If value-initialization involves calling a constructor, should - // we make that call explicit in the representation (even when it means - // extending the initializer list)? - if (Init < NumInits && !hadError) - ILE->setInit(Init, - new (SemaRef.Context) ImplicitValueInitExpr(ElementType)); + Sema::OwningExprResult ElementInit + = InitSeq.Perform(SemaRef, ElementEntity, Kind, + Sema::MultiExprArg(SemaRef, 0, 0)); + if (ElementInit.isInvalid()) { + hadError = true; + return; + } + + if (hadError) { + // Do nothing + } else if (Init < NumInits) { + ILE->setInit(Init, ElementInit.takeAs<Expr>()); + } else if (InitSeq.getKind() + == InitializationSequence::ConstructorInitialization) { + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(Init, ElementInit.takeAs<Expr>()); + RequiresSecondPass = true; + } } else if (InitListExpr *InnerILE - = dyn_cast<InitListExpr>(ILE->getInit(Init))) - FillInValueInitializations(InnerILE); + = dyn_cast<InitListExpr>(ILE->getInit(Init))) + FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass); } } -InitListChecker::InitListChecker(Sema &S, InitListExpr *IL, QualType &T) +InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, + InitListExpr *IL, QualType &T) : SemaRef(S) { hadError = false; @@ -511,8 +435,13 @@ InitListChecker::InitListChecker(Sema &S, InitListExpr *IL, QualType &T) CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex, /*TopLevelObject=*/true); - if (!hadError) - FillInValueInitializations(FullyStructuredList); + if (!hadError) { + bool RequiresSecondPass = false; + FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass); + if (RequiresSecondPass && !hadError) + FillInValueInitializations(Entity, FullyStructuredList, + RequiresSecondPass); + } } int InitListChecker::numArrayElements(QualType DeclType) { @@ -743,7 +672,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion) { if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS, - "initializing")) + Sema::AA_Initializing)) hadError = true; UpdateStructuredListElement(StructuredList, StructuredIndex, expr); ++Index; @@ -783,7 +712,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, } else { // We cannot initialize this element, so let // PerformCopyInitialization produce the appropriate diagnostic. - SemaRef.PerformCopyInitialization(expr, ElemType, "initializing"); + SemaRef.PerformCopyInitialization(expr, ElemType, Sema::AA_Initializing); hadError = true; ++Index; ++StructuredIndex; @@ -1358,22 +1287,33 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, // may find nothing, or may find a member of an anonymous // struct/union. DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName); + FieldDecl *ReplacementField = 0; if (Lookup.first == Lookup.second) { - // Name lookup didn't find anything. - SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) - << FieldName << CurrentObjectType; - ++Index; - return true; - } else if (!KnownField && isa<FieldDecl>(*Lookup.first) && - cast<RecordDecl>((*Lookup.first)->getDeclContext()) - ->isAnonymousStructOrUnion()) { - // Handle an field designator that refers to a member of an - // anonymous struct or union. - ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, - cast<FieldDecl>(*Lookup.first), - Field, FieldIndex); - D = DIE->getDesignator(DesigIdx); - } else { + // Name lookup didn't find anything. Determine whether this + // was a typo for another field name. + LookupResult R(SemaRef, FieldName, D->getFieldLoc(), + Sema::LookupMemberName); + if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl()) && + (ReplacementField = R.getAsSingle<FieldDecl>()) && + ReplacementField->getDeclContext()->getLookupContext() + ->Equals(RT->getDecl())) { + SemaRef.Diag(D->getFieldLoc(), + diag::err_field_designator_unknown_suggest) + << FieldName << CurrentObjectType << R.getLookupName() + << CodeModificationHint::CreateReplacement(D->getFieldLoc(), + R.getLookupName().getAsString()); + } else { + SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) + << FieldName << CurrentObjectType; + ++Index; + return true; + } + } else if (!KnownField) { + // Determine whether we found a field at all. + ReplacementField = dyn_cast<FieldDecl>(*Lookup.first); + } + + if (!ReplacementField) { // Name lookup found something, but it wasn't a field. SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield) << FieldName; @@ -1382,6 +1322,32 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, ++Index; 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) { + // The replacement field comes from typo correction; find it + // in the list of fields. + FieldIndex = 0; + Field = RT->getDecl()->field_begin(); + for (; Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + if (ReplacementField == *Field || + Field->getIdentifier() == ReplacementField->getIdentifier()) + break; + + ++FieldIndex; + } + } } else if (!KnownField && cast<RecordDecl>((*Field)->getDeclContext()) ->isAnonymousStructOrUnion()) { @@ -1844,101 +1810,27 @@ Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, return Owned(DIE); } -bool Sema::CheckInitList(InitListExpr *&InitList, QualType &DeclType) { - InitListChecker CheckInitList(*this, InitList, DeclType); +bool Sema::CheckInitList(const InitializedEntity &Entity, + InitListExpr *&InitList, QualType &DeclType) { + InitListChecker CheckInitList(*this, Entity, InitList, DeclType); if (!CheckInitList.HadError()) InitList = CheckInitList.getFullyStructuredList(); return CheckInitList.HadError(); } -/// \brief Diagnose any semantic errors with value-initialization of -/// the given type. -/// -/// Value-initialization effectively zero-initializes any types -/// without user-declared constructors, and calls the default -/// constructor for a for any type that has a user-declared -/// constructor (C++ [dcl.init]p5). Value-initialization can fail when -/// a type with a user-declared constructor does not have an -/// accessible, non-deleted default constructor. In C, everything can -/// be value-initialized, which corresponds to C's notion of -/// initializing objects with static storage duration when no -/// initializer is provided for that object. -/// -/// \returns true if there was an error, false otherwise. -bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) { - // C++ [dcl.init]p5: - // - // To value-initialize an object of type T means: - - // -- if T is an array type, then each element is value-initialized; - if (const ArrayType *AT = Context.getAsArrayType(Type)) - return CheckValueInitialization(AT->getElementType(), Loc); - - if (const RecordType *RT = Type->getAs<RecordType>()) { - if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - // -- if T is a class type (clause 9) with a user-declared - // constructor (12.1), then the default constructor for T is - // called (and the initialization is ill-formed if T has no - // accessible default constructor); - if (ClassDecl->hasUserDeclaredConstructor()) { - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - - // FIXME: Poor location information - CXXConstructorDecl *Constructor - = PerformInitializationByConstructor(Type, - MultiExprArg(*this, 0, 0), - Loc, SourceRange(Loc), - DeclarationName(), - InitializationKind::CreateValue(Loc, Loc, Loc), - ConstructorArgs); - if (!Constructor) - return true; - - OwningExprResult Init - = BuildCXXConstructExpr(Loc, Type, Constructor, - move_arg(ConstructorArgs)); - if (Init.isInvalid()) - return true; - - // FIXME: Actually perform the value-initialization! - return false; - } - } - } - - if (Type->isReferenceType()) { - // C++ [dcl.init]p5: - // [...] A program that calls for default-initialization or - // value-initialization of an entity of reference type is - // ill-formed. [...] - // FIXME: Once we have code that goes through this path, add an actual - // diagnostic :) - } - - return false; -} - //===----------------------------------------------------------------------===// // Initialization entity //===----------------------------------------------------------------------===// -void InitializedEntity::InitDeclLoc() { - assert((Kind == EK_Variable || Kind == EK_Parameter || Kind == EK_Member) && - "InitDeclLoc cannot be used with non-declaration entities."); - - if (TypeSourceInfo *DI = VariableOrMember->getTypeSourceInfo()) { - TL = DI->getTypeLoc(); - return; - } - - // FIXME: Once we've gone through the effort to create the fake - // TypeSourceInfo, should we cache it in the declaration? - // (If not, we "leak" it). - TypeSourceInfo *DI = VariableOrMember->getASTContext() - .CreateTypeSourceInfo(VariableOrMember->getType()); - DI->getTypeLoc().initialize(VariableOrMember->getLocation()); - TL = DI->getTypeLoc(); +InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, + const InitializedEntity &Parent) + : Kind(EK_ArrayOrVectorElement), Parent(&Parent), Index(Index) +{ + if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) + Type = AT->getElementType(); + else + Type = Parent.getType()->getAs<VectorType>()->getElementType(); } InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, @@ -1947,13 +1839,54 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, InitializedEntity Result; Result.Kind = EK_Base; Result.Base = Base; - // FIXME: CXXBaseSpecifier should store a TypeLoc. - TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Base->getType()); - DI->getTypeLoc().initialize(Base->getSourceRange().getBegin()); - Result.TL = DI->getTypeLoc(); + Result.Type = Base->getType(); return Result; } +DeclarationName InitializedEntity::getName() const { + switch (getKind()) { + case EK_Parameter: + if (!VariableOrMember) + return DeclarationName(); + // Fall through + + case EK_Variable: + case EK_Member: + return VariableOrMember->getDeclName(); + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_ArrayOrVectorElement: + return DeclarationName(); + } + + // Silence GCC warning + return DeclarationName(); +} + +DeclaratorDecl *InitializedEntity::getDecl() const { + switch (getKind()) { + case EK_Variable: + case EK_Parameter: + case EK_Member: + return VariableOrMember; + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_ArrayOrVectorElement: + return 0; + } + + // Silence GCC warning + return 0; +} + //===----------------------------------------------------------------------===// // Initialization sequence //===----------------------------------------------------------------------===// @@ -1971,6 +1904,8 @@ void InitializationSequence::Step::Destroy() { case SK_ListInitialization: case SK_ConstructorInitialization: case SK_ZeroInitialization: + case SK_CAssignment: + case SK_StringInit: break; case SK_ConversionSequence: @@ -2056,6 +1991,20 @@ void InitializationSequence::AddZeroInitializationStep(QualType T) { Steps.push_back(S); } +void InitializationSequence::AddCAssignmentStep(QualType T) { + Step S; + S.Kind = SK_CAssignment; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddStringInitStep(QualType T) { + Step S; + S.Kind = SK_StringInit; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::SetOverloadFailure(FailureKind Failure, OverloadingResult Result) { SequenceKind = FailedSequence; @@ -2081,7 +2030,7 @@ static void TryListInitialization(Sema &S, // force us to perform more checking here. Sequence.setSequenceKind(InitializationSequence::ListInitialization); - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); // C++ [dcl.init]p13: // If T is a scalar type, then a declaration of the form @@ -2125,7 +2074,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, Expr *Initializer, bool AllowRValues, InitializationSequence &Sequence) { - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); QualType T1 = cv1T1.getUnqualifiedType(); QualType cv2T2 = Initializer->getType(); @@ -2273,7 +2222,7 @@ static void TryReferenceInitialization(Sema &S, InitializationSequence &Sequence) { Sequence.setSequenceKind(InitializationSequence::ReferenceBinding); - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); QualType T1 = cv1T1.getUnqualifiedType(); QualType cv2T2 = Initializer->getType(); @@ -2437,7 +2386,12 @@ static void TryReferenceInitialization(Sema &S, // this into an overloading ambiguity diagnostic. However, we need // to keep that set as an OverloadCandidateSet rather than as some // other kind of set. - Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed); + if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + else + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed); return; } @@ -2463,7 +2417,8 @@ static void TryStringLiteralInitialization(Sema &S, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence) { - // FIXME: Implement! + Sequence.setSequenceKind(InitializationSequence::StringInit); + Sequence.AddStringInitStep(Entity.getType()); } /// \brief Attempt initialization by constructor (C++ [dcl.init]), which @@ -2475,7 +2430,10 @@ static void TryConstructorInitialization(Sema &S, Expr **Args, unsigned NumArgs, QualType DestType, InitializationSequence &Sequence) { - Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization); + if (Kind.getKind() == InitializationKind::IK_Copy) + Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion); + else + Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization); // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. @@ -2512,7 +2470,7 @@ static void TryConstructorInitialization(Sema &S, Constructor = cast<CXXConstructorDecl>(*Con); if (!Constructor->isInvalidDecl() && - Constructor->isConvertingConstructor(AllowExplicit)) { + (AllowExplicit || !Constructor->isExplicit())) { if (ConstructorTmpl) S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0, Args, NumArgs, CandidateSet); @@ -2535,9 +2493,13 @@ static void TryConstructorInitialization(Sema &S, // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. - Sequence.AddConstructorInitializationStep( + if (Kind.getKind() == InitializationKind::IK_Copy) { + Sequence.AddUserConversionStep(Best->Function, DestType); + } else { + Sequence.AddConstructorInitializationStep( cast<CXXConstructorDecl>(Best->Function), - DestType); + DestType); + } } /// \brief Attempt value initialization (C++ [dcl.init]p7). @@ -2548,7 +2510,7 @@ static void TryValueInitialization(Sema &S, // C++ [dcl.init]p5: // // To value-initialize an object of type T means: - QualType T = Entity.getType().getType(); + QualType T = Entity.getType(); // -- if T is an array type, then each element is value-initialized; while (const ArrayType *AT = S.Context.getAsArrayType(T)) @@ -2566,15 +2528,58 @@ static void TryValueInitialization(Sema &S, if (ClassDecl->hasUserDeclaredConstructor()) return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); - // FIXME: non-union class type w/ non-trivial default constructor gets - // zero-initialized, then constructor gets called. + // -- 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 + // constructor is non-trivial, that constructor is called. + if ((ClassDecl->getTagKind() == TagDecl::TK_class || + ClassDecl->getTagKind() == TagDecl::TK_struct) && + !ClassDecl->hasTrivialConstructor()) { + Sequence.AddZeroInitializationStep(Entity.getType()); + return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); + } } } - Sequence.AddZeroInitializationStep(Entity.getType().getType()); + Sequence.AddZeroInitializationStep(Entity.getType()); Sequence.setSequenceKind(InitializationSequence::ZeroInitialization); } +/// \brief Attempt default initialization (C++ [dcl.init]p6). +static void TryDefaultInitialization(Sema &S, + const InitializedEntity &Entity, + 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); + if (DestType->isRecordType()) { + // FIXME: 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 + // default constructor. + return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, + Sequence); + } + + // - 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 + // default constructor. + if (DestType.isConstQualified()) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); +} + /// \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. @@ -2585,7 +2590,7 @@ static void TryUserDefinedConversion(Sema &S, InitializationSequence &Sequence) { Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion); - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); assert(!DestType->isReferenceType() && "References are handled elsewhere"); QualType SourceType = Initializer->getType(); assert((DestType->isRecordType() || SourceType->isRecordType()) && @@ -2632,43 +2637,49 @@ static void TryUserDefinedConversion(Sema &S, } } } - + + SourceLocation DeclLoc = Initializer->getLocStart(); + if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) { // The type we're converting from is a class type, enumerate its conversion // functions. - CXXRecordDecl *SourceRecordDecl - = cast<CXXRecordDecl>(SourceRecordType->getDecl()); - - const UnresolvedSet *Conversions - = SourceRecordDecl->getVisibleConversionFunctions(); - for (UnresolvedSet::iterator I = Conversions->begin(), - 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>(*I); + + // We can only enumerate the conversion functions for a complete type; if + // the type isn't complete, simply skip this step. + if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) { + CXXRecordDecl *SourceRecordDecl + = cast<CXXRecordDecl>(SourceRecordType->getDecl()); - if (AllowExplicit || !Conv->isExplicit()) { + const UnresolvedSet *Conversions + = SourceRecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSet::iterator I = Conversions->begin(), + 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) - S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, Initializer, - DestType, CandidateSet); + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); else - S.AddConversionCandidate(Conv, ActingDC, Initializer, DestType, - CandidateSet); + Conv = cast<CXXConversionDecl>(*I); + + if (AllowExplicit || !Conv->isExplicit()) { + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, + Initializer, DestType, + CandidateSet); + else + S.AddConversionCandidate(Conv, ActingDC, Initializer, DestType, + CandidateSet); + } } } } - SourceLocation DeclLoc = Initializer->getLocStart(); - // Perform overload resolution. If it fails, return the failed result. OverloadCandidateSet::iterator Best; if (OverloadingResult Result @@ -2711,7 +2722,7 @@ static void TryImplicitConversion(Sema &S, Expr *Initializer, InitializationSequence &Sequence) { ImplicitConversionSequence ICS - = S.TryImplicitConversion(Initializer, Entity.getType().getType(), + = S.TryImplicitConversion(Initializer, Entity.getType(), /*SuppressUserConversions=*/true, /*AllowExplicit=*/false, /*ForceRValue=*/false, @@ -2723,7 +2734,7 @@ static void TryImplicitConversion(Sema &S, return; } - Sequence.AddConversionSequenceStep(ICS, Entity.getType().getType()); + Sequence.AddConversionSequenceStep(ICS, Entity.getType()); } InitializationSequence::InitializationSequence(Sema &S, @@ -2739,7 +2750,7 @@ InitializationSequence::InitializationSequence(Sema &S, // 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 // parenthesized list of expressions. - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); if (DestType->isDependentType() || Expr::hasAnyTypeDependentArguments(Args, NumArgs)) { @@ -2749,7 +2760,7 @@ InitializationSequence::InitializationSequence(Sema &S, QualType SourceType; Expr *Initializer = 0; - if (Kind.getKind() == InitializationKind::IK_Copy) { + if (NumArgs == 1) { Initializer = Args[0]; if (!isa<InitListExpr>(Initializer)) SourceType = Initializer->getType(); @@ -2785,11 +2796,18 @@ InitializationSequence::InitializationSequence(Sema &S, } // - If the initializer is (), the object is value-initialized. - if (Kind.getKind() == InitializationKind::IK_Value) { + 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){ + TryDefaultInitialization(S, Entity, Kind, *this); + return; + } + // - Otherwise, if the destination type is an array, the program is // ill-formed. if (const ArrayType *AT = Context.getAsArrayType(DestType)) { @@ -2800,6 +2818,13 @@ InitializationSequence::InitializationSequence(Sema &S, return; } + + // Handle initialization in C + if (!S.getLangOptions().CPlusPlus) { + setSequenceKind(CAssignment); + AddCAssignmentStep(DestType); + return; + } // - If the destination type is a (possibly cv-qualified) class type: if (DestType->isRecordType()) { @@ -2812,7 +2837,7 @@ InitializationSequence::InitializationSequence(Sema &S, (Context.hasSameUnqualifiedType(SourceType, DestType) || S.IsDerivedFrom(SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, NumArgs, - Entity.getType().getType(), *this); + Entity.getType(), *this); // - 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 @@ -2824,9 +2849,15 @@ InitializationSequence::InitializationSequence(Sema &S, 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 // type, conversion functions are considered. - if (SourceType->isRecordType()) { + if (!SourceType.isNull() && SourceType->isRecordType()) { TryUserDefinedConversion(S, Entity, Kind, Initializer, *this); return; } @@ -2836,6 +2867,7 @@ InitializationSequence::InitializationSequence(Sema &S, // conversions (Clause 4) will be used, if necessary, to convert the // initializer expression to the cv-unqualified version of the // destination type; no user-defined conversions are considered. + setSequenceKind(StandardConversion); TryImplicitConversion(S, Entity, Kind, Initializer, *this); } @@ -2849,6 +2881,158 @@ InitializationSequence::~InitializationSequence() { //===----------------------------------------------------------------------===// // Perform initialization //===----------------------------------------------------------------------===// +static Sema::AssignmentAction +getAssignmentAction(const InitializedEntity &Entity) { + switch(Entity.getKind()) { + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_New: + return Sema::AA_Initializing; + + case InitializedEntity::EK_Parameter: + // FIXME: Can we tell when we're sending vs. passing? + return Sema::AA_Passing; + + 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_ArrayOrVectorElement: + return Sema::AA_Initializing; + } + + return Sema::AA_Converting; +} + +static bool shouldBindAsTemporary(const InitializedEntity &Entity, + bool IsCopy) { + switch (Entity.getKind()) { + case InitializedEntity::EK_Result: + case InitializedEntity::EK_Exception: + return !IsCopy; + + case InitializedEntity::EK_New: + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_ArrayOrVectorElement: + return false; + + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + return true; + } + + llvm_unreachable("missed an InitializedEntity kind?"); +} + +/// \brief If we need to perform an additional copy of the initialized object +/// for this kind of entity (e.g., the result of a function or an object being +/// thrown), make the copy. +static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Sema::OwningExprResult CurInit) { + SourceLocation Loc; + + switch (Entity.getKind()) { + case InitializedEntity::EK_Result: + if (Entity.getType()->isReferenceType()) + return move(CurInit); + Loc = Entity.getReturnLoc(); + break; + + case InitializedEntity::EK_Exception: + Loc = Entity.getThrowLoc(); + break; + + case InitializedEntity::EK_Variable: + if (Entity.getType()->isReferenceType() || + Kind.getKind() != InitializationKind::IK_Copy) + return move(CurInit); + Loc = Entity.getDecl()->getLocation(); + break; + + case InitializedEntity::EK_Parameter: + // FIXME: Do we need this initialization for a parameter? + return move(CurInit); + + case InitializedEntity::EK_New: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_ArrayOrVectorElement: + // We don't need to copy for any of these initialized entities. + return move(CurInit); + } + + Expr *CurInitExpr = (Expr *)CurInit.get(); + CXXRecordDecl *Class = 0; + if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>()) + Class = cast<CXXRecordDecl>(Record->getDecl()); + if (!Class) + return move(CurInit); + + // Perform overload resolution using the class's copy constructors. + DeclarationName ConstructorName + = S.Context.DeclarationNames.getCXXConstructorName( + S.Context.getCanonicalType(S.Context.getTypeDeclType(Class))); + DeclContext::lookup_iterator Con, ConEnd; + OverloadCandidateSet CandidateSet; + for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName); + Con != ConEnd; ++Con) { + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con); + if (!Constructor || Constructor->isInvalidDecl() || + !Constructor->isCopyConstructor()) + continue; + + S.AddOverloadCandidate(Constructor, &CurInitExpr, 1, CandidateSet); + } + + OverloadCandidateSet::iterator Best; + switch (S.BestViableFunction(CandidateSet, Loc, Best)) { + case OR_Success: + break; + + case OR_No_Viable_Function: + S.Diag(Loc, diag::err_temp_copy_no_viable) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + S.PrintOverloadCandidates(CandidateSet, false); + return S.ExprError(); + + case OR_Ambiguous: + S.Diag(Loc, diag::err_temp_copy_ambiguous) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + S.PrintOverloadCandidates(CandidateSet, true); + return S.ExprError(); + + case OR_Deleted: + S.Diag(Loc, diag::err_temp_copy_deleted) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) + << Best->Function->isDeleted(); + return S.ExprError(); + } + + CurInit.release(); + return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(), + cast<CXXConstructorDecl>(Best->Function), + /*Elidable=*/true, + Sema::MultiExprArg(S, + (void**)&CurInitExpr, 1)); +} Action::OwningExprResult InitializationSequence::Perform(Sema &S, @@ -2866,9 +3050,9 @@ InitializationSequence::Perform(Sema &S, // If the declaration is a non-dependent, incomplete array type // that has an initializer, then its type will be completed once // the initializer is instantiated. - if (ResultType && !Entity.getType().getType()->isDependentType() && + if (ResultType && !Entity.getType()->isDependentType() && Args.size() == 1) { - QualType DeclType = Entity.getType().getType(); + QualType DeclType = Entity.getType(); if (const IncompleteArrayType *ArrayT = S.Context.getAsIncompleteArrayType(DeclType)) { // FIXME: We don't currently have the ability to accurately @@ -2880,11 +3064,15 @@ InitializationSequence::Perform(Sema &S, // bound. if (isa<InitListExpr>((Expr *)Args.get()[0])) { SourceRange Brackets; + // Scavange the location of the brackets from the entity, if we can. - if (isa<IncompleteArrayTypeLoc>(Entity.getType())) { - IncompleteArrayTypeLoc ArrayLoc - = cast<IncompleteArrayTypeLoc>(Entity.getType()); - Brackets = ArrayLoc.getBracketsRange(); + if (DeclaratorDecl *DD = Entity.getDecl()) { + if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { + TypeLoc TL = TInfo->getTypeLoc(); + if (IncompleteArrayTypeLoc *ArrayLoc + = dyn_cast<IncompleteArrayTypeLoc>(&TL)) + Brackets = ArrayLoc->getBracketsRange(); + } } *ResultType @@ -2898,7 +3086,7 @@ InitializationSequence::Perform(Sema &S, } } - if (Kind.getKind() == InitializationKind::IK_Copy) + if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast()) return Sema::OwningExprResult(S, Args.release()[0]); unsigned NumArgs = Args.size(); @@ -2909,34 +3097,58 @@ InitializationSequence::Perform(Sema &S, SourceLocation())); } - QualType DestType = Entity.getType().getType().getNonReferenceType(); + 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, + // and we want latter when it makes sense. if (ResultType) - *ResultType = Entity.getType().getType(); - - Sema::OwningExprResult CurInit(S); - // For copy initialization and any other initialization forms that - // only have a single initializer, we start with the (only) - // initializer we have. - // FIXME: DPG is not happy about this. There's confusion regarding whether - // we're supposed to start the conversion from the solitary initializer or - // from the set of arguments. - if (Kind.getKind() == InitializationKind::IK_Copy || - SequenceKind != ConstructorInitialization) { + *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() : + Entity.getType(); + + Sema::OwningExprResult CurInit = S.Owned((Expr *)0); + + assert(!Steps.empty() && "Cannot have an empty initialization sequence"); + + // 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) { + case SK_ResolveAddressOfOverloadedFunction: + case SK_CastDerivedToBaseRValue: + case SK_CastDerivedToBaseLValue: + case SK_BindReference: + case SK_BindReferenceToTemporary: + case SK_UserConversion: + case SK_QualificationConversionLValue: + case SK_QualificationConversionRValue: + case SK_ConversionSequence: + case SK_ListInitialization: + case SK_CAssignment: + case SK_StringInit: assert(Args.size() == 1); - CurInit = Sema::OwningExprResult(S, Args.release()[0]); + CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain()); if (CurInit.isInvalid()) return S.ExprError(); + break; + + case SK_ConstructorInitialization: + case SK_ZeroInitialization: + break; } // 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 S.ExprError(); Expr *CurInitExpr = (Expr *)CurInit.get(); - QualType SourceType = CurInitExpr->getType(); + QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType(); switch (Step->Kind) { case SK_ResolveAddressOfOverloadedFunction: @@ -2969,7 +3181,7 @@ InitializationSequence::Perform(Sema &S, if (FieldDecl *BitField = CurInitExpr->getBitField()) { // References cannot bind to bit fields (C++ [dcl.init.ref]p5). S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) - << Entity.getType().getType().isVolatileQualified() + << Entity.getType().isVolatileQualified() << BitField->getDeclName() << CurInitExpr->getSourceRange(); S.Diag(BitField->getLocation(), diag::note_bitfield_decl); @@ -2996,6 +3208,7 @@ InitializationSequence::Perform(Sema &S, // We have a user-defined conversion that invokes either a constructor // or a conversion function. CastExpr::CastKind CastKind = CastExpr::CK_Unknown; + bool IsCopy = false; if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Step->Function)) { // Build a call to the selected constructor. @@ -3019,10 +3232,14 @@ InitializationSequence::Perform(Sema &S, return S.ExprError(); CastKind = CastExpr::CK_ConstructorConversion; + QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); + if (S.Context.hasSameUnqualifiedType(SourceType, Class) || + S.IsDerivedFrom(SourceType, Class)) + IsCopy = true; } else { // Build a call to the conversion function. CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Step->Function); - + // 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. @@ -3041,12 +3258,17 @@ InitializationSequence::Perform(Sema &S, CastKind = CastExpr::CK_UserDefinedConversion; } - CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + if (shouldBindAsTemporary(Entity, IsCopy)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + CurInitExpr = CurInit.takeAs<Expr>(); CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(), CastKind, CurInitExpr, - false)); + false)); + + if (!IsCopy) + CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit)); break; } @@ -3061,7 +3283,7 @@ InitializationSequence::Perform(Sema &S, break; case SK_ConversionSequence: - if (S.PerformImplicitConversion(CurInitExpr, Step->Type, "converting", + if (S.PerformImplicitConversion(CurInitExpr, Step->Type, Sema::AA_Converting, false, false, *Step->ICS)) return S.ExprError(); @@ -3072,7 +3294,7 @@ InitializationSequence::Perform(Sema &S, case SK_ListInitialization: { InitListExpr *InitList = cast<InitListExpr>(CurInitExpr); QualType Ty = Step->Type; - if (S.CheckInitList(InitList, ResultType? *ResultType : Ty)) + if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty)) return S.ExprError(); CurInit.release(); @@ -3095,22 +3317,68 @@ InitializationSequence::Perform(Sema &S, return S.ExprError(); // Build the an expression that constructs a temporary. - CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, - move_arg(ConstructorArgs)); + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, + move_arg(ConstructorArgs), + ConstructorInitRequiresZeroInit); if (CurInit.isInvalid()) return S.ExprError(); - - CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + + bool Elidable + = cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable(); + if (shouldBindAsTemporary(Entity, Elidable)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + + if (!Elidable) + CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit)); break; } case SK_ZeroInitialization: { - if (Kind.getKind() == InitializationKind::IK_Value) + step_iterator NextStep = Step; + ++NextStep; + 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. + ConstructorInitRequiresZeroInit = true; + } else if (Kind.getKind() == InitializationKind::IK_Value && + S.getLangOptions().CPlusPlus && + !Kind.isImplicitValueInit()) { CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type, Kind.getRange().getBegin(), Kind.getRange().getEnd())); - else + } else { CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type)); + } + break; + } + + case SK_CAssignment: { + QualType SourceType = CurInitExpr->getType(); + Sema::AssignConvertType ConvTy = + S.CheckSingleAssignmentConstraints(Step->Type, CurInitExpr); + + // If this is a call, allow conversion to a transparent union. + if (ConvTy != Sema::Compatible && + Entity.getKind() == InitializedEntity::EK_Parameter && + S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExpr) + == Sema::Compatible) + ConvTy = Sema::Compatible; + + if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), + Step->Type, SourceType, + CurInitExpr, getAssignmentAction(Entity))) + return S.ExprError(); + + CurInit.release(); + CurInit = S.Owned(CurInitExpr); + break; + } + + case SK_StringInit: { + QualType Ty = Step->Type; + CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S); break; } } @@ -3129,7 +3397,7 @@ bool InitializationSequence::Diagnose(Sema &S, if (SequenceKind != FailedSequence) return false; - QualType DestType = Entity.getType().getType(); + QualType DestType = Entity.getType(); switch (Failure) { case FK_TooManyInitsForReference: S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) @@ -3152,9 +3420,15 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_UserConversionOverloadFailed: switch (FailedOverloadResult) { case OR_Ambiguous: - S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) - << Args[0]->getType() << DestType.getNonReferenceType() - << Args[0]->getSourceRange(); + if (Failure == FK_UserConversionOverloadFailed) + S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) + << Args[0]->getType() << DestType + << Args[0]->getSourceRange(); + else + S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous) + << DestType << Args[0]->getType() + << Args[0]->getSourceRange(); + S.PrintOverloadCandidates(FailedCandidateSet, true); break; @@ -3220,7 +3494,8 @@ bool InitializationSequence::Diagnose(Sema &S, break; case FK_ConversionFailed: - S.Diag(Kind.getLocation(), diag::err_cannot_initialize_decl_noname) + S.Diag(Kind.getLocation(), diag::err_init_conversion_failed) + << (int)Entity.getKind() << DestType << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid) << Args[0]->getType() @@ -3228,12 +3503,16 @@ bool InitializationSequence::Diagnose(Sema &S, break; case FK_TooManyInitsForScalar: { - InitListExpr *InitList = cast<InitListExpr>(Args[0]); + SourceRange R; + + if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0])) + R = SourceRange(InitList->getInit(1)->getLocStart(), + InitList->getLocEnd()); + else + R = SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); S.Diag(Kind.getLocation(), diag::err_excess_initializers) - << /*scalar=*/2 - << SourceRange(InitList->getInit(1)->getLocStart(), - InitList->getLocEnd()); + << /*scalar=*/2 << R; break; } @@ -3290,7 +3569,36 @@ bool InitializationSequence::Diagnose(Sema &S, } break; } + + case FK_DefaultInitOfConst: + S.Diag(Kind.getLocation(), diag::err_default_init_const) + << DestType; + break; } return true; } + +//===----------------------------------------------------------------------===// +// Initialization helper functions +//===----------------------------------------------------------------------===// +Sema::OwningExprResult +Sema::PerformCopyInitialization(const InitializedEntity &Entity, + SourceLocation EqualLoc, + OwningExprResult Init) { + if (Init.isInvalid()) + return ExprError(); + + Expr *InitE = (Expr *)Init.get(); + assert(InitE && "No initialization expression?"); + + if (EqualLoc.isInvalid()) + EqualLoc = InitE->getLocStart(); + + InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), + EqualLoc); + InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); + Init.release(); + return Seq.Perform(*this, Entity, Kind, + MultiExprArg(*this, (void**)&InitE, 1)); +} |