diff options
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 76 |
1 files changed, 57 insertions, 19 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index adec512693f3..c3a89463dc69 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -443,8 +443,11 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, if (!VerifyOnly) { SemaRef.Diag(CtorDecl->getLocation(), diag::warn_invalid_initializer_from_system_header); - SemaRef.Diag(Entity.getDecl()->getLocation(), - diag::note_used_in_initialization_here); + if (Entity.getKind() == InitializedEntity::EK_Member) + SemaRef.Diag(Entity.getDecl()->getLocation(), + diag::note_used_in_initialization_here); + else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) + SemaRef.Diag(Loc, diag::note_used_in_initialization_here); } } } @@ -802,7 +805,8 @@ void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); // Update the structured sub-object initializer so that it's ending // range corresponds with the end of the last initializer it used. - if (EndIndex < ParentIList->getNumInits()) { + if (EndIndex < ParentIList->getNumInits() && + ParentIList->getInit(EndIndex)) { SourceLocation EndLoc = ParentIList->getInit(EndIndex)->getSourceRange().getEnd(); StructuredSubobjectInitList->setRBraceLoc(EndLoc); @@ -3008,6 +3012,7 @@ bool InitializationSequence::isAmbiguous() const { case FK_VariableLengthArrayHasInitializer: case FK_PlaceholderType: case FK_ExplicitConstructor: + case FK_AddressOfUnaddressableFunction: return false; case FK_ReferenceInitOverloadFailed: @@ -3323,7 +3328,7 @@ static bool TryInitializerListConstruction(Sema &S, if (!S.isStdInitializerList(DestType, &E)) return false; - if (S.RequireCompleteType(List->getExprLoc(), E, 0)) { + if (!S.isCompleteType(List->getExprLoc(), E)) { Sequence.setIncompleteTypeFailure(E); return true; } @@ -3433,7 +3438,7 @@ static void TryConstructorInitialization(Sema &S, "IsListInit must come with a single initializer list argument."); // The type we're constructing needs to be complete. - if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { + if (!S.isCompleteType(Kind.getLocation(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } @@ -3674,7 +3679,7 @@ static void TryListInitialization(Sema &S, } if (DestType->isRecordType() && - S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) { + !S.isCompleteType(InitList->getLocStart(), DestType)) { Sequence.setIncompleteTypeFailure(DestType); return; } @@ -3694,7 +3699,7 @@ static void TryListInitialization(Sema &S, if (DestType->isRecordType()) { QualType InitType = InitList->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, DestType) || - S.IsDerivedFrom(InitType, DestType)) { + S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) { Expr *InitAsExpr = InitList->getInit(0); TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType, Sequence, /*InitListSyntax*/ false, @@ -3728,7 +3733,9 @@ static void TryListInitialization(Sema &S, // C++11 [dcl.init.list]p3: // - If T is an aggregate, aggregate initialization is performed. - if (DestType->isRecordType() && !DestType->isAggregateType()) { + if ((DestType->isRecordType() && !DestType->isAggregateType()) || + (S.getLangOpts().CPlusPlus11 && + S.isStdInitializerList(DestType, nullptr))) { if (S.getLangOpts().CPlusPlus11) { // - Otherwise, if the initializer list has no elements and T is a // class type with a default constructor, the object is @@ -3834,7 +3841,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const RecordType *T1RecordType = nullptr; if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) && - !S.RequireCompleteType(Kind.getLocation(), T1, 0)) { + S.isCompleteType(Kind.getLocation(), T1)) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl()); @@ -3870,7 +3877,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const RecordType *T2RecordType = nullptr; if ((T2RecordType = T2->getAs<RecordType>()) && - !S.RequireCompleteType(Kind.getLocation(), T2, 0)) { + S.isCompleteType(Kind.getLocation(), T2)) { // The type we're converting from is a class type, enumerate its conversion // functions. CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl()); @@ -4455,7 +4462,7 @@ static void TryUserDefinedConversion(Sema &S, = cast<CXXRecordDecl>(DestRecordType->getDecl()); // Try to complete the type we're converting to. - if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { + if (S.isCompleteType(Kind.getLocation(), DestType)) { DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl); // The container holding the constructors can under certain conditions // be changed while iterating. To be safe we copy the lookup results @@ -4501,7 +4508,7 @@ static void TryUserDefinedConversion(Sema &S, // 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)) { + if (S.isCompleteType(DeclLoc, SourceType)) { CXXRecordDecl *SourceRecordDecl = cast<CXXRecordDecl>(SourceRecordType->getDecl()); @@ -4798,6 +4805,17 @@ InitializationSequence::InitializationSequence(Sema &S, InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList); } +/// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the +/// address of that function, this returns true. Otherwise, it returns false. +static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) { + auto *DRE = dyn_cast<DeclRefExpr>(E); + if (!DRE || !isa<FunctionDecl>(DRE->getDecl())) + return false; + + return !S.checkAddressOfFunctionIsAvailable( + cast<FunctionDecl>(DRE->getDecl())); +} + void InitializationSequence::InitializeFrom(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -4979,7 +4997,7 @@ void InitializationSequence::InitializeFrom(Sema &S, } assert(S.getLangOpts().CPlusPlus); - + // - If the destination type is a (possibly cv-qualified) class type: if (DestType->isRecordType()) { // - If the initialization is direct-initialization, or if it is @@ -4989,7 +5007,7 @@ void InitializationSequence::InitializeFrom(Sema &S, if (Kind.getKind() == InitializationKind::IK_Direct || (Kind.getKind() == InitializationKind::IK_Copy && (Context.hasSameUnqualifiedType(SourceType, DestType) || - S.IsDerivedFrom(SourceType, DestType)))) + S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, DestType, *this); // - Otherwise (i.e., for the remaining copy-initialization cases), @@ -5018,7 +5036,8 @@ void InitializationSequence::InitializeFrom(Sema &S, bool NeedAtomicConversion = false; if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) { if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) || - S.IsDerivedFrom(SourceType, Atomic->getValueType())) { + S.IsDerivedFrom(Initializer->getLocStart(), SourceType, + Atomic->getValueType())) { DestType = Atomic->getValueType(); NeedAtomicConversion = true; } @@ -5076,6 +5095,9 @@ void InitializationSequence::InitializeFrom(Sema &S, !S.ResolveAddressOfOverloadedFunction(Initializer, DestType, false, dap)) SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + else if (Initializer->getType()->isFunctionType() && + isExprAnUnaddressableFunction(S, Initializer)) + SetFailed(InitializationSequence::FK_AddressOfUnaddressableFunction); else SetFailed(InitializationSequence::FK_ConversionFailed); } else { @@ -6357,7 +6379,7 @@ InitializationSequence::Perform(Sema &S, CastKind = CK_ConstructorConversion; QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); if (S.Context.hasSameUnqualifiedType(SourceType, Class) || - S.IsDerivedFrom(SourceType, Class)) + S.IsDerivedFrom(Loc, SourceType, Class)) IsCopy = true; CreatedObject = true; @@ -6596,6 +6618,8 @@ InitializationSequence::Perform(Sema &S, case SK_CAssignment: { QualType SourceType = CurInit.get()->getType(); + // Save off the initial CurInit in case we need to emit a diagnostic + ExprResult InitialCurInit = CurInit; ExprResult Result = CurInit; Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(Step->Type, Result, true, @@ -6618,7 +6642,7 @@ InitializationSequence::Perform(Sema &S, bool Complained; if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, - CurInit.get(), + InitialCurInit.get(), getAssignmentAction(Entity, true), &Complained)) { PrintInitLocationNote(S, Entity); @@ -6921,6 +6945,13 @@ bool InitializationSequence::Diagnose(Sema &S, break; } + case FK_AddressOfUnaddressableFunction: { + auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(Args[0])->getDecl()); + S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true, + Args[0]->getLocStart()); + break; + } + case FK_ReferenceInitOverloadFailed: case FK_UserConversionOverloadFailed: switch (FailedOverloadResult) { @@ -6943,6 +6974,7 @@ bool InitializationSequence::Diagnose(Sema &S, diag::err_typecheck_nonviable_condition_incomplete, Args[0]->getType(), Args[0]->getSourceRange())) S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) + << (Entity.getKind() == InitializedEntity::EK_Result) << Args[0]->getType() << Args[0]->getSourceRange() << DestType.getNonReferenceType(); @@ -7043,10 +7075,12 @@ bool InitializationSequence::Diagnose(Sema &S, SourceRange R; auto *InitList = dyn_cast<InitListExpr>(Args[0]); - if (InitList && InitList->getNumInits() == 1) + if (InitList && InitList->getNumInits() >= 1) { R = SourceRange(InitList->getInit(0)->getLocEnd(), InitList->getLocEnd()); - else + } else { + assert(Args.size() > 1 && "Expected multiple initializers!"); R = SourceRange(Args.front()->getLocEnd(), Args.back()->getLocEnd()); + } R.setBegin(S.getLocForEndOfToken(R.getBegin())); if (Kind.isCStyleOrFunctionalCast()) @@ -7240,6 +7274,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "array requires initializer list"; break; + case FK_AddressOfUnaddressableFunction: + OS << "address of unaddressable function was taken"; + break; + case FK_ArrayNeedsInitListOrStringLiteral: OS << "array requires initializer list or string literal"; break; |