forked from OSchip/llvm-project
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. llvm-svn: 256049
This commit is contained in:
parent
9a217b6787
commit
db0ac5572f
|
@ -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<Ts...>());
|
||||
DB << T;
|
||||
|
@ -1367,7 +1365,7 @@ public:
|
|||
|
||||
private:
|
||||
bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
|
||||
TypeDiagnoser &Diagnoser);
|
||||
TypeDiagnoser *Diagnoser);
|
||||
|
||||
VisibleModuleSet VisibleModules;
|
||||
llvm::SmallVector<VisibleModuleSet, 16> VisibleModulesStack;
|
||||
|
@ -1413,6 +1411,9 @@ public:
|
|||
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,
|
||||
|
@ -5502,6 +5503,7 @@ public:
|
|||
AbstractArrayType
|
||||
};
|
||||
|
||||
bool isAbstractType(SourceLocation Loc, QualType T);
|
||||
bool RequireNonAbstractType(SourceLocation Loc, QualType T,
|
||||
TypeDiagnoser &Diagnoser);
|
||||
template <typename... Ts>
|
||||
|
@ -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]
|
||||
//
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -4052,7 +4052,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> 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();
|
||||
|
|
|
@ -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<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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<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 {
|
||||
|
|
|
@ -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<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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RecordType>())
|
||||
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<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());
|
||||
|
@ -3877,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());
|
||||
|
@ -4462,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
|
||||
|
@ -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<CXXRecordDecl>(SourceRecordType->getDecl());
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<CXXRecordDecl>(ToRecordType->getDecl())) {
|
||||
|
@ -3159,7 +3159,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
|
|||
|
||||
// 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>()) {
|
||||
|
@ -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<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())
|
||||
|
@ -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<CXXRecordDecl>(TyRec->getDecl());
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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!");
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1998,7 +1998,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
|
|||
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,
|
||||
|
@ -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<TagType>()) {
|
||||
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<MemberPointerType>()) {
|
||||
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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue