From 5dbd903a7e109d970f48ae9f5baa76eed52e72fd Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 18 Dec 2015 22:40:25 +0000 Subject: [PATCH] Split RequireCompleteType into a function that actually requires that the type is complete (with an error produced if not) and a function that merely queries whether the type is complete. Either way we'll trigger instantiation if necessary, but only the former will diagnose and recover from missing module imports. The intent of this change is to prevent a class of bugs where code would call RequireCompleteType(..., 0) and then ignore the result. With modules, we must check the return value and use it to determine whether the definition of the type is visible. This also fixes a debug info quality issue: calls to isCompleteType do not trigger the emission of debug information for a type in limited-debug-info mode. This allows us to avoid emitting debug information for type definitions in more cases where we believe it is safe to do so. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@256049 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 19 ++++--- lib/Sema/SemaCast.cpp | 13 +++-- lib/Sema/SemaCodeComplete.cpp | 4 +- lib/Sema/SemaDeclCXX.cpp | 73 ++++++++------------------ lib/Sema/SemaDeclObjC.cpp | 2 + lib/Sema/SemaExpr.cpp | 9 ++-- lib/Sema/SemaExprCXX.cpp | 11 ++-- lib/Sema/SemaExprObjC.cpp | 2 + lib/Sema/SemaInit.cpp | 14 ++--- lib/Sema/SemaLookup.cpp | 4 +- lib/Sema/SemaOverload.cpp | 25 ++++----- lib/Sema/SemaStmt.cpp | 9 ++-- lib/Sema/SemaStmtAsm.cpp | 3 +- lib/Sema/SemaTemplate.cpp | 2 +- lib/Sema/SemaTemplateDeduction.cpp | 6 ++- lib/Sema/SemaType.cpp | 33 ++++++------ test/CodeGenCXX/debug-info-limited.cpp | 3 +- 17 files changed, 106 insertions(+), 126 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index acb30f2de5..94fd00bf02 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1316,9 +1316,7 @@ public: /// \brief Abstract class used to diagnose incomplete types. struct TypeDiagnoser { - bool Suppressed; - - TypeDiagnoser(bool Suppressed = false) : Suppressed(Suppressed) { } + TypeDiagnoser() {} virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0; virtual ~TypeDiagnoser() {} @@ -1354,11 +1352,11 @@ public: public: BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args) - : TypeDiagnoser(DiagID == 0), DiagID(DiagID), Args(Args...) {} + : TypeDiagnoser(), DiagID(DiagID), Args(Args...) { + assert(DiagID != 0 && "no diagnostic for type diagnoser"); + } void diagnose(Sema &S, SourceLocation Loc, QualType T) override { - if (Suppressed) - return; const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID); emit(DB, llvm::index_sequence_for()); DB << T; @@ -1367,7 +1365,7 @@ public: private: bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser); + TypeDiagnoser *Diagnoser); VisibleModuleSet VisibleModules; llvm::SmallVector VisibleModulesStack; @@ -1413,6 +1411,9 @@ public: SourceLocation Loc, const NamedDecl *D, ArrayRef Equiv); + bool isCompleteType(SourceLocation Loc, QualType T) { + return !RequireCompleteTypeImpl(Loc, T, nullptr); + } bool RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser); bool RequireCompleteType(SourceLocation Loc, QualType T, @@ -5502,6 +5503,7 @@ public: AbstractArrayType }; + bool isAbstractType(SourceLocation Loc, QualType T); bool RequireNonAbstractType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser); template @@ -5513,9 +5515,6 @@ public: void DiagnoseAbstractType(const CXXRecordDecl *RD); - bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, - AbstractDiagSelID SelID = AbstractNone); - //===--------------------------------------------------------------------===// // C++ Overloaded Operators [C++ 13.5] // diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 1cc97fcd9d..07b058911c 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -1262,8 +1262,8 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, QualType OrigDestType, unsigned &msg, CastKind &Kind, CXXCastPath &BasePath) { // We can only work with complete types. But don't complain if it doesn't work - if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0) || - Self.RequireCompleteType(OpRange.getBegin(), DestType, 0)) + if (!Self.isCompleteType(OpRange.getBegin(), SrcType) || + !Self.isCompleteType(OpRange.getBegin(), DestType)) return TC_NotApplicable; // Downcast can only happen in class hierarchies, so we need classes. @@ -1399,8 +1399,11 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, msg = diag::err_bad_static_cast_member_pointer_nonmp; return TC_NotApplicable; } + + // Lock down the inheritance model right now in MS ABI, whether or not the + // pointee types are the same. if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) - Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0); + (void)Self.isCompleteType(OpRange.getBegin(), SrcType); // T == T, modulo cv if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(), @@ -1844,8 +1847,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) { // We need to determine the inheritance model that the class will use if // haven't yet. - Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0); - Self.RequireCompleteType(OpRange.getBegin(), DestType, 0); + (void)Self.isCompleteType(OpRange.getBegin(), SrcType); + (void)Self.isCompleteType(OpRange.getBegin(), DestType); } // Don't allow casting between member pointers of different sizes. diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 20a1eb1a6b..52151f6759 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -4052,7 +4052,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef Args) { // If expression's type is CXXRecordDecl, it may overload the function // call operator, so we check if it does and add them as candidates. // A complete type is needed to lookup for member function call operators. - if (!RequireCompleteType(Loc, NakedFn->getType(), 0)) { + if (isCompleteType(Loc, NakedFn->getType())) { DeclarationName OpName = Context.DeclarationNames .getCXXOperatorName(OO_Call); LookupResult R(*this, OpName, Loc, LookupOrdinaryName); @@ -4094,7 +4094,7 @@ void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, return; // A complete type is needed to lookup for constructors. - if (RequireCompleteType(Loc, Type, 0)) + if (!isCompleteType(Loc, Type)) return; CXXRecordDecl *RD = Type->getAsCXXRecordDecl(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 2cc0d071a9..f67e573c74 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1673,11 +1673,6 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { if (!DerivedRD) return false; - // FIXME: In a modules build, do we need the entire path to be visible for us - // to be able to use the inheritance relationship? - if (RequireCompleteType(Loc, Derived, 0) && !DerivedRD->isBeingDefined()) - return false; - CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); if (!BaseRD) return false; @@ -1687,6 +1682,11 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl()) return false; + // FIXME: In a modules build, do we need the entire path to be visible for us + // to be able to use the inheritance relationship? + if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) + return false; + return DerivedRD->isDerivedFrom(BaseRD); } @@ -1701,13 +1701,13 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, if (!DerivedRD) return false; - if (RequireCompleteType(Loc, Derived, 0) && !DerivedRD->isBeingDefined()) - return false; - CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); if (!BaseRD) return false; + if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) + return false; + return DerivedRD->isDerivedFrom(BaseRD, Paths); } @@ -4420,64 +4420,35 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { } } -bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, - unsigned DiagID, AbstractDiagSelID SelID) { - class NonAbstractTypeDiagnoser : public TypeDiagnoser { - unsigned DiagID; - AbstractDiagSelID SelID; - - public: - NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID) - : TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { } - - void diagnose(Sema &S, SourceLocation Loc, QualType T) override { - if (Suppressed) return; - if (SelID == -1) - S.Diag(Loc, DiagID) << T; - else - S.Diag(Loc, DiagID) << SelID << T; - } - } Diagnoser(DiagID, SelID); - - return RequireNonAbstractType(Loc, T, Diagnoser); -} - -bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser) { +bool Sema::isAbstractType(SourceLocation Loc, QualType T) { if (!getLangOpts().CPlusPlus) return false; - if (const ArrayType *AT = Context.getAsArrayType(T)) - return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); - - if (const PointerType *PT = T->getAs()) { - // Find the innermost pointer type. - while (const PointerType *T = PT->getPointeeType()->getAs()) - PT = T; - - if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) - return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); - } - - const RecordType *RT = T->getAs(); - if (!RT) + const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl(); + if (!RD) return false; - const CXXRecordDecl *RD = cast(RT->getDecl()); + // FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a + // class template specialization here, but doing so breaks a lot of code. // We can't answer whether something is abstract until it has a - // definition. If it's currently being defined, we'll walk back + // definition. If it's currently being defined, we'll walk back // over all the declarations when we have a full definition. const CXXRecordDecl *Def = RD->getDefinition(); if (!Def || Def->isBeingDefined()) return false; - if (!RD->isAbstract()) + return RD->isAbstract(); +} + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + TypeDiagnoser &Diagnoser) { + if (!isAbstractType(Loc, T)) return false; + T = Context.getBaseElementType(T); Diagnoser.diagnose(*this, Loc, T); - DiagnoseAbstractType(RD); - + DiagnoseAbstractType(T->getAsCXXRecordDecl()); return true; } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 6f0206f088..a2f41a7cc3 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1867,6 +1867,8 @@ Decl *Sema::ActOnStartClassImplementation( Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; Diag(PrevDecl->getLocation(), diag::note_previous_definition); } else if ((IDecl = dyn_cast_or_null(PrevDecl))) { + // FIXME: This will produce an error if the definition of the interface has + // been imported from a module but is not visible. RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), diag::warn_undef_interface); } else { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d31a816b80..ac7e98c583 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -686,9 +686,10 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (T.hasQualifiers()) T = T.getUnqualifiedType(); + // Under the MS ABI, lock down the inheritance model now. if (T->isMemberPointerType() && Context.getTargetInfo().getCXXABI().isMicrosoft()) - RequireCompleteType(E->getExprLoc(), T, 0); + (void)isCompleteType(E->getExprLoc(), T); UpdateMarkingForLValueToRValue(E); @@ -9947,8 +9948,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { QualType MPTy = Context.getMemberPointerType( op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); + // Under the MS ABI, lock down the inheritance model now. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) - RequireCompleteType(OpLoc, MPTy, 0); + (void)isCompleteType(OpLoc, MPTy); return MPTy; } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) { // C99 6.5.3.2p1 @@ -10003,8 +10005,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { QualType MPTy = Context.getMemberPointerType( op->getType(), Context.getTypeDeclType(cast(Ctx)).getTypePtr()); + // Under the MS ABI, lock down the inheritance model now. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) - RequireCompleteType(OpLoc, MPTy, 0); + (void)isCompleteType(OpLoc, MPTy); return MPTy; } } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 1604a70d52..47d15c363c 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2717,6 +2717,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return ExprError(Diag(StartLoc, diag::err_delete_operand) << Type << Ex.get()->getSourceRange()); } else if (!Pointee->isDependentType()) { + // FIXME: This can result in errors if the definition was imported from a + // module but is hidden. if (!RequireCompleteType(StartLoc, Pointee, diag::warn_delete_incomplete, Ex.get())) { if (const RecordType *RT = PointeeElem->getAs()) @@ -2792,7 +2794,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (!OperatorDelete) // Look for a global declaration. OperatorDelete = FindUsualDeallocationFunction( - StartLoc, !RequireCompleteType(StartLoc, Pointee, 0) && + StartLoc, isCompleteType(StartLoc, Pointee) && (!ArrayForm || UsualArrayDeleteWantsSize || Pointee.isDestructedType()), DeleteName); @@ -3309,8 +3311,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // We may not have been able to figure out what this member pointer resolved // to up until this exact point. Attempt to lock-in it's inheritance model. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - RequireCompleteType(From->getExprLoc(), From->getType(), 0); - RequireCompleteType(From->getExprLoc(), ToType, 0); + (void)isCompleteType(From->getExprLoc(), From->getType()); + (void)isCompleteType(From->getExprLoc(), ToType); } From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) @@ -4291,8 +4293,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, return LhsT->isVoidType(); // A function definition requires a complete, non-abstract return type. - if (Self.RequireCompleteType(KeyLoc, RhsT, 0) || - Self.RequireNonAbstractType(KeyLoc, RhsT, 0)) + if (!Self.isCompleteType(KeyLoc, RhsT) || Self.isAbstractType(KeyLoc, RhsT)) return false; // Compute the result of add_rvalue_reference. diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index a179957e98..c1ac621b57 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -2726,6 +2726,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // Try to complete the type. Under ARC, this is a hard error from which // we don't try to recover. + // FIXME: In the non-ARC case, this will still be a hard error if the + // definition is found in a module that's not visible. const ObjCInterfaceDecl *forwardClass = nullptr; if (RequireCompleteType(Loc, OCIType->getPointeeType(), getLangOpts().ObjCAutoRefCount diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 1f0504fd38..c3a89463dc 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3328,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; } @@ -3438,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; } @@ -3679,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; } @@ -3841,7 +3841,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const RecordType *T1RecordType = nullptr; if (AllowRValues && (T1RecordType = T1->getAs()) && - !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(T1RecordType->getDecl()); @@ -3877,7 +3877,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const RecordType *T2RecordType = nullptr; if ((T2RecordType = T2->getAs()) && - !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(T2RecordType->getDecl()); @@ -4462,7 +4462,7 @@ static void TryUserDefinedConversion(Sema &S, = cast(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 @@ -4508,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(SourceRecordType->getDecl()); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 434fc7540c..f56b722bca 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2428,8 +2428,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, } // Only recurse into base classes for complete types. - if (Result.S.RequireCompleteType(Result.InstantiationLoc, - Result.S.Context.getRecordType(Class), 0)) + if (!Result.S.isCompleteType(Result.InstantiationLoc, + Result.S.Context.getRecordType(Class))) return; // Add direct and indirect base classes along with their associated diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 58949bfd44..62f4f18bd3 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1822,7 +1822,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // We have already pre-calculated the promotion type, so this is trivial. if (ToType->isIntegerType() && - !RequireCompleteType(From->getLocStart(), FromType, 0)) + isCompleteType(From->getLocStart(), FromType)) return Context.hasSameUnqualifiedType( ToType, FromEnumType->getDecl()->getPromotionType()); } @@ -3085,7 +3085,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, S.IsDerivedFrom(From->getLocStart(), From->getType(), ToType))) ConstructorsOnly = true; - if (S.RequireCompleteType(From->getExprLoc(), ToType, 0)) { + if (!S.isCompleteType(From->getExprLoc(), ToType)) { // We're not going to find any constructors. } else if (CXXRecordDecl *ToRecordDecl = dyn_cast(ToRecordType->getDecl())) { @@ -3159,7 +3159,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Enumerate conversion functions, if we're allowed to. if (ConstructorsOnly || isa(From)) { - } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), 0)) { + } else if (!S.isCompleteType(From->getLocStart(), From->getType())) { // No conversion functions from incomplete types. } else if (const RecordType *FromRecordType = From->getType()->getAs()) { @@ -4047,7 +4047,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, ObjCLifetimeConversion = false; if (UnqualT1 == UnqualT2) { // Nothing to do. - } else if (!RequireCompleteType(Loc, OrigT2, 0) && + } else if (isCompleteType(Loc, OrigT2) && isTypeValid(UnqualT1) && isTypeValid(UnqualT2) && IsDerivedFrom(Loc, UnqualT2, UnqualT1)) DerivedToBase = true; @@ -4314,7 +4314,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // conversion functions (13.3.1.6) and choosing the best // one through overload resolution (13.3)), if (!SuppressUserConversions && T2->isRecordType() && - !S.RequireCompleteType(DeclLoc, T2, 0) && + S.isCompleteType(DeclLoc, T2) && RefRelationship == Sema::Ref_Incompatible) { if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc, Init, T2, /*AllowRvalues=*/false, @@ -4377,7 +4377,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // in the second case (or, in either case, to an appropriate base // class subobject). if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible && - T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) && + T2->isRecordType() && S.isCompleteType(DeclLoc, T2) && FindConversionForRefInit(S, ICS, DeclType, DeclLoc, Init, T2, /*AllowRvalues=*/true, AllowExplicit)) { @@ -4515,7 +4515,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // We need a complete type for what follows. Incomplete types can never be // initialized from init lists. - if (S.RequireCompleteType(From->getLocStart(), ToType, 0)) + if (!S.isCompleteType(From->getLocStart(), ToType)) return Result; // Per DR1467: @@ -5449,14 +5449,15 @@ ExprResult Sema::PerformContextualImplicitConversion( Expr *From; TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From) - : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {} + : Converter(Converter), From(From) {} void diagnose(Sema &S, SourceLocation Loc, QualType T) override { Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange(); } } IncompleteDiagnoser(Converter, From); - if (RequireCompleteType(Loc, T, IncompleteDiagnoser)) + if (Converter.Suppress ? !isCompleteType(Loc, T) + : RequireCompleteType(Loc, T, IncompleteDiagnoser)) return From; // Look for a conversion to an integral or enumeration type. @@ -6432,7 +6433,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, &ConversionRef, VK_RValue); QualType ConversionType = Conversion->getConversionType(); - if (RequireCompleteType(From->getLocStart(), ConversionType, 0)) { + if (!isCompleteType(From->getLocStart(), ConversionType)) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_final_conversion; return; @@ -6681,7 +6682,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, // the set of member candidates is empty. if (const RecordType *T1Rec = T1->getAs()) { // Complete the type if it can be completed. - if (RequireCompleteType(OpLoc, T1, 0) && !T1Rec->isBeingDefined()) + if (!isCompleteType(OpLoc, T1) && !T1Rec->isBeingDefined()) return; // If the type is neither complete nor being defined, bail out now. if (!T1Rec->getDecl()->getDefinition()) @@ -7031,7 +7032,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, HasNullPtrType = true; } else if (AllowUserConversions && TyRec) { // No conversion functions in incomplete types. - if (SemaRef.RequireCompleteType(Loc, Ty, 0)) + if (!SemaRef.isCompleteType(Loc, Ty)) return; CXXRecordDecl *ClassDecl = cast(TyRec->getDecl()); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index ac6813e5fe..e1b1a47e18 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1706,11 +1706,10 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { // If we have a forward-declared type, we can't do this check. // Under ARC, it is an error not to have a forward-declared class. if (iface && - RequireCompleteType(forLoc, QualType(objectType, 0), - getLangOpts().ObjCAutoRefCount - ? diag::err_arc_collection_forward - : 0, - collection)) { + (getLangOpts().ObjCAutoRefCount + ? RequireCompleteType(forLoc, QualType(objectType, 0), + diag::err_arc_collection_forward, collection) + : !isCompleteType(forLoc, QualType(objectType, 0)))) { // Otherwise, if we have any useful type information, check that // the type declares the appropriate method. } else if (iface || !objectType->qual_empty()) { diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 6991fd999b..2917c5a360 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -647,7 +647,8 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, if (!RT) return true; - if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0)) + if (RequireCompleteType(AsmLoc, QualType(RT, 0), + diag::err_asm_incomplete_type)) return true; LookupResult FieldResult(*this, &Context.Idents.get(NextMember), diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index bd868139df..9ef927f1c1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4282,7 +4282,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, if (Arg->isValueDependent() || Arg->isTypeDependent()) return NPV_NotNullPointer; - if (S.RequireCompleteType(Arg->getExprLoc(), ParamType, 0)) + if (!S.isCompleteType(Arg->getExprLoc(), ParamType)) llvm_unreachable( "Incomplete parameter type in isNullPointerValueTemplateArgument!"); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 66b9abc300..18ad12a63c 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1440,7 +1440,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, // We cannot inspect base classes as part of deduction when the type // is incomplete, so either instantiate any templates necessary to // complete the type, or skip over it if it cannot be completed. - if (S.RequireCompleteType(Info.getLocation(), Arg, 0)) + if (!S.isCompleteType(Info.getLocation(), Arg)) return Result; // Use data recursion to crawl through the list of base classes. @@ -3132,8 +3132,10 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, if (ParamRefType) { // If the argument has incomplete array type, try to complete its type. - if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0)) + if (ArgType->isIncompleteArrayType()) { + S.completeExprArrayBound(Arg); ArgType = Arg->getType(); + } // C++0x [temp.deduct.call]p3: // If P is an rvalue reference to a cv-unqualified template diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index f44b01f8ac..c70568c23b 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1998,7 +1998,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (Context.getTargetInfo().getCXXABI().isMicrosoft()) if (const MemberPointerType *MPTy = T->getAs()) if (!MPTy->getClass()->isDependentType()) - RequireCompleteType(Loc, T, 0); + (void)isCompleteType(Loc, T); } else { // C99 6.7.5.2p1: If the element type is an incomplete or function type, @@ -2126,12 +2126,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (T->isVariableArrayType()) { // Prohibit the use of non-POD types in VLAs. QualType BaseT = Context.getBaseElementType(T); - if (!T->isDependentType() && - !RequireCompleteType(Loc, BaseT, 0) && - !BaseT.isPODType(Context) && - !BaseT->isObjCLifetimeType()) { - Diag(Loc, diag::err_vla_non_pod) - << BaseT; + if (!T->isDependentType() && isCompleteType(Loc, BaseT) && + !BaseT.isPODType(Context) && !BaseT->isObjCLifetimeType()) { + Diag(Loc, diag::err_vla_non_pod) << BaseT; return QualType(); } // Prohibit the use of VLAs during template argument deduction. @@ -6466,7 +6463,7 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) { /// @c false otherwise. bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser) { - if (RequireCompleteTypeImpl(Loc, T, Diagnoser)) + if (RequireCompleteTypeImpl(Loc, T, &Diagnoser)) return true; if (const TagType *Tag = T->getAs()) { if (!Tag->getDecl()->isCompleteDefinitionRequired()) { @@ -6570,7 +6567,7 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { /// \brief The implementation of RequireCompleteType bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser) { + TypeDiagnoser *Diagnoser) { // FIXME: Add this assertion to make sure we always get instantiation points. // assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType"); // FIXME: Add this assertion to help us flush out problems with @@ -6584,7 +6581,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { if (const MemberPointerType *MPTy = T->getAs()) { if (!MPTy->getClass()->isDependentType()) { - RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0); + (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0)); assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl()); } } @@ -6599,8 +6596,8 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) { // If the user is going to see an error here, recover by making the // definition visible. - bool TreatAsComplete = !Diagnoser.Suppressed && !isSFINAEContext(); - if (!Diagnoser.Suppressed) + bool TreatAsComplete = Diagnoser && !isSFINAEContext(); + if (Diagnoser) diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true, /*Recover*/TreatAsComplete); return !TreatAsComplete; @@ -6660,7 +6657,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) { Diagnosed = InstantiateClassTemplateSpecialization( Loc, ClassTemplateSpec, TSK_ImplicitInstantiation, - /*Complain=*/!Diagnoser.Suppressed); + /*Complain=*/Diagnoser); Instantiated = true; } } else if (CXXRecordDecl *Rec @@ -6675,7 +6672,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, Diagnosed = InstantiateClass(Loc, Rec, Pattern, getTemplateInstantiationArgs(Rec), TSK_ImplicitInstantiation, - /*Complain=*/!Diagnoser.Suppressed); + /*Complain=*/Diagnoser); Instantiated = true; } } @@ -6684,7 +6681,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, if (Instantiated) { // Instantiate* might have already complained that the template is not // defined, if we asked it to. - if (!Diagnoser.Suppressed && Diagnosed) + if (Diagnoser && Diagnosed) return true; // If we instantiated a definition, check that it's usable, even if // instantiation produced an error, so that repeated calls to this @@ -6694,7 +6691,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, } } - if (Diagnoser.Suppressed) + if (!Diagnoser) return true; // We have an incomplete type. Produce a diagnostic. @@ -6704,7 +6701,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, return true; } - Diagnoser.diagnose(*this, Loc, T); + Diagnoser->diagnose(*this, Loc, T); // If the type was a forward declaration of a class/struct/union // type, produce a note. @@ -6769,7 +6766,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, assert(!T->isDependentType() && "type should not be dependent"); QualType ElemType = Context.getBaseElementType(T); - if ((!RequireCompleteType(Loc, ElemType, 0) || ElemType->isVoidType()) && + if ((isCompleteType(Loc, ElemType) || ElemType->isVoidType()) && T->isLiteralType(Context)) return false; diff --git a/test/CodeGenCXX/debug-info-limited.cpp b/test/CodeGenCXX/debug-info-limited.cpp index d56e5b670a..b209e3a850 100644 --- a/test/CodeGenCXX/debug-info-limited.cpp +++ b/test/CodeGenCXX/debug-info-limited.cpp @@ -14,8 +14,7 @@ A *foo (A* x) { } // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "B" -// CHECK-NOT: DIFlagFwdDecl -// CHECK-SAME: ){{$}} +// CHECK-SAME: flags: DIFlagFwdDecl class B { public: -- 2.40.0