/// \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() {}
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<Ts...>());
DB << T;
private:
bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser);
+ TypeDiagnoser *Diagnoser);
VisibleModuleSet VisibleModules;
llvm::SmallVector<VisibleModuleSet, 16> VisibleModulesStack;
SourceLocation Loc, const NamedDecl *D,
ArrayRef<const NamedDecl *> 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,
AbstractArrayType
};
+ bool isAbstractType(SourceLocation Loc, QualType T);
bool RequireNonAbstractType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser);
template <typename... Ts>
void DiagnoseAbstractType(const CXXRecordDecl *RD);
- bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
- AbstractDiagSelID SelID = AbstractNone);
-
//===--------------------------------------------------------------------===//
// C++ Overloaded Operators [C++ 13.5]
//
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.
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(),
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.
// 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);
return;
// A complete type is needed to lookup for constructors.
- if (RequireCompleteType(Loc, Type, 0))
+ if (!isCompleteType(Loc, Type))
return;
CXXRecordDecl *RD = Type->getAsCXXRecordDecl();
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;
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);
}
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);
}
}
}
-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<PointerType>()) {
- // Find the innermost pointer type.
- while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>())
- PT = T;
-
- if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
- return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser);
- }
-
- const RecordType *RT = T->getAs<RecordType>();
- if (!RT)
+ const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl();
+ if (!RD)
return false;
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(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;
}
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
} else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(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 {
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);
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
QualType MPTy = Context.getMemberPointerType(
op->getType(),
Context.getTypeDeclType(cast<RecordDecl>(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;
}
}
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<RecordType>())
if (!OperatorDelete)
// Look for a global declaration.
OperatorDelete = FindUsualDeallocationFunction(
- StartLoc, !RequireCompleteType(StartLoc, Pointee, 0) &&
+ StartLoc, isCompleteType(StartLoc, Pointee) &&
(!ArrayForm || UsualArrayDeleteWantsSize ||
Pointee.isDestructedType()),
DeleteName);
// 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)
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.
// 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
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;
}
"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;
}
}
if (DestType->isRecordType() &&
- S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) {
+ !S.isCompleteType(InitList->getLocStart(), DestType)) {
Sequence.setIncompleteTypeFailure(DestType);
return;
}
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());
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());
= 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
// 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());
}
// 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
// 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());
}
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<CXXRecordDecl>(ToRecordType->getDecl())) {
// Enumerate conversion functions, if we're allowed to.
if (ConstructorsOnly || isa<InitListExpr>(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<RecordType>()) {
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;
// 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,
// 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)) {
// 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:
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.
&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;
// the set of member candidates is empty.
if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
// 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())
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<CXXRecordDecl>(TyRec->getDecl());
// 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()) {
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),
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!");
// 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.
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
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
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,
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.
/// @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<TagType>()) {
if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
/// \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
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
if (!MPTy->getClass()->isDependentType()) {
- RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
+ (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
}
}
!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;
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
Diagnosed = InstantiateClassTemplateSpecialization(
Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
- /*Complain=*/!Diagnoser.Suppressed);
+ /*Complain=*/Diagnoser);
Instantiated = true;
}
} else if (CXXRecordDecl *Rec
Diagnosed = InstantiateClass(Loc, Rec, Pattern,
getTemplateInstantiationArgs(Rec),
TSK_ImplicitInstantiation,
- /*Complain=*/!Diagnoser.Suppressed);
+ /*Complain=*/Diagnoser);
Instantiated = true;
}
}
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
}
}
- if (Diagnoser.Suppressed)
+ if (!Diagnoser)
return true;
// We have an incomplete type. Produce a diagnostic.
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.
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;
}
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "B"
-// CHECK-NOT: DIFlagFwdDecl
-// CHECK-SAME: ){{$}}
+// CHECK-SAME: flags: DIFlagFwdDecl
class B {
public: