Move Sema::RequireCompleteType() and Sema::RequireCompleteExprType()

off PartialDiagnostic. PartialDiagnostic is rather heavyweight for
something that is in the critical path and is rarely used. So, switch
over to an abstract-class-based callback mechanism that delays most of
the work until a diagnostic is actually produced. Good for ~11k code
size reduction in the compiler and 1% speedup in -fsyntax-only on the
code in <rdar://problem/11004361>.

llvm-svn: 156176
This commit is contained in:
Douglas Gregor 2012-05-04 16:32:21 +00:00
parent 5ff430ce06
commit 7bfb2d026e
18 changed files with 294 additions and 168 deletions

View File

@ -944,16 +944,140 @@ public:
/// in an Objective-C message declaration. Return the appropriate type.
ParsedType ActOnObjCInstanceType(SourceLocation Loc);
/// \brief Abstract class used to diagnose incomplete types.
struct IncompleteTypeDiagnoser {
bool Suppressed;
IncompleteTypeDiagnoser(bool Suppressed = false) : Suppressed(Suppressed) { }
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
virtual ~IncompleteTypeDiagnoser() {}
};
static int getPrintable(int I) { return I; }
static bool getPrintable(bool B) { return B; }
static const char * getPrintable(const char *S) { return S; }
static StringRef getPrintable(StringRef S) { return S; }
static const std::string &getPrintable(const std::string &S) { return S; }
static const IdentifierInfo *getPrintable(const IdentifierInfo *II) {
return II;
}
static DeclarationName getPrintable(DeclarationName N) { return N; }
static QualType getPrintable(QualType T) { return T; }
static SourceRange getPrintable(SourceRange R) { return R; }
static SourceRange getPrintable(SourceLocation L) { return L; }
static SourceRange getPrintable(Expr *E) { return E->getSourceRange(); }
static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange();}
template<typename T1>
class BoundIncompleteTypeDiagnoser1 : public IncompleteTypeDiagnoser {
unsigned DiagID;
const T1 &Arg1;
public:
BoundIncompleteTypeDiagnoser1(unsigned DiagID, const T1 &Arg1)
: IncompleteTypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1) { }
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
if (Suppressed) return;
S.Diag(Loc, DiagID) << getPrintable(Arg1) << T;
}
virtual ~BoundIncompleteTypeDiagnoser1() { }
};
template<typename T1, typename T2>
class BoundIncompleteTypeDiagnoser2 : public IncompleteTypeDiagnoser {
unsigned DiagID;
const T1 &Arg1;
const T2 &Arg2;
public:
BoundIncompleteTypeDiagnoser2(unsigned DiagID, const T1 &Arg1,
const T2 &Arg2)
: IncompleteTypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1),
Arg2(Arg2) { }
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
if (Suppressed) return;
S.Diag(Loc, DiagID) << getPrintable(Arg1) << getPrintable(Arg2) << T;
}
virtual ~BoundIncompleteTypeDiagnoser2() { }
};
template<typename T1, typename T2, typename T3>
class BoundIncompleteTypeDiagnoser3 : public IncompleteTypeDiagnoser {
unsigned DiagID;
const T1 &Arg1;
const T2 &Arg2;
const T3 &Arg3;
public:
BoundIncompleteTypeDiagnoser3(unsigned DiagID, const T1 &Arg1,
const T2 &Arg2, const T3 &Arg3)
: IncompleteTypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1),
Arg2(Arg2), Arg3(Arg3) { }
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
if (Suppressed) return;
S.Diag(Loc, DiagID)
<< getPrintable(Arg1) << getPrintable(Arg2) << getPrintable(Arg3) << T;
}
virtual ~BoundIncompleteTypeDiagnoser3() { }
};
bool RequireCompleteType(SourceLocation Loc, QualType T,
const PartialDiagnostic &PD,
std::pair<SourceLocation, PartialDiagnostic> Note);
bool RequireCompleteType(SourceLocation Loc, QualType T,
const PartialDiagnostic &PD);
IncompleteTypeDiagnoser &Diagnoser);
bool RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID);
bool RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
std::pair<SourceLocation,
PartialDiagnostic> Note);
template<typename T1>
bool RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID, const T1 &Arg1) {
BoundIncompleteTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1);
return RequireCompleteType(Loc, T, Diagnoser);
}
template<typename T1, typename T2>
bool RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID, const T1 &Arg1, const T2 &Arg2) {
BoundIncompleteTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2);
return RequireCompleteType(Loc, T, Diagnoser);
}
template<typename T1, typename T2, typename T3>
bool RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID, const T1 &Arg1, const T2 &Arg2,
const T3 &Arg3) {
BoundIncompleteTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2,
Arg3);
return RequireCompleteType(Loc, T, Diagnoser);
}
bool RequireCompleteExprType(Expr *E, IncompleteTypeDiagnoser &Diagnoser);
bool RequireCompleteExprType(Expr *E, unsigned DiagID);
template<typename T1>
bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1) {
BoundIncompleteTypeDiagnoser1<T1> Diagnoser(DiagID, Arg1);
return RequireCompleteExprType(E, Diagnoser);
}
template<typename T1, typename T2>
bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1,
const T2 &Arg2) {
BoundIncompleteTypeDiagnoser2<T1, T2> Diagnoser(DiagID, Arg1, Arg2);
return RequireCompleteExprType(E, Diagnoser);
}
template<typename T1, typename T2, typename T3>
bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1,
const T2 &Arg2, const T3 &Arg3) {
BoundIncompleteTypeDiagnoser3<T1, T2, T3> Diagnoser(DiagID, Arg1, Arg2,
Arg3);
return RequireCompleteExprType(E, Diagnoser);
}
bool RequireLiteralType(SourceLocation Loc, QualType T,
const PartialDiagnostic &PD);

View File

@ -227,9 +227,8 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
if (loc.isInvalid()) loc = SS.getRange().getBegin();
// The type must be complete.
if (RequireCompleteType(loc, type,
PDiag(diag::err_incomplete_nested_name_spec)
<< SS.getRange())) {
if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec,
SS.getRange())) {
SS.SetInvalid(SS.getRange());
return true;
}

View File

@ -561,8 +561,8 @@ void CastOperation::CheckDynamicCast() {
assert(DestPointer && "Reference to void is not possible");
} else if (DestRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
<< DestRange))
diag::err_bad_dynamic_cast_incomplete,
DestRange))
return;
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
@ -597,8 +597,8 @@ void CastOperation::CheckDynamicCast() {
const RecordType *SrcRecord = SrcPointee->getAs<RecordType>();
if (SrcRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
Self.PDiag(diag::err_bad_dynamic_cast_incomplete)
<< SrcExpr.get()->getSourceRange()))
diag::err_bad_dynamic_cast_incomplete,
SrcExpr.get()))
return;
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
@ -1075,8 +1075,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, Self.PDiag(0)) ||
Self.RequireCompleteType(OpRange.getBegin(), DestType, Self.PDiag(0)))
if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0) ||
Self.RequireCompleteType(OpRange.getBegin(), DestType, 0))
return TC_NotApplicable;
// Downcast can only happen in class hierarchies, so we need classes.

View File

@ -4488,7 +4488,7 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd,
// This is also C++ [dcl.fct]p6.
if (!Param->isInvalidDecl() &&
RequireCompleteType(Param->getLocation(), Param->getType(),
diag::err_typecheck_decl_incomplete_type)) {
diag::err_typecheck_decl_incomplete_type)) {
Param->setInvalidDecl();
HasInvalidParm = true;
}

View File

@ -1055,8 +1055,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
// The class-name in a base-specifier shall not be an incompletely
// defined class.
if (RequireCompleteType(BaseLoc, BaseType,
PDiag(diag::err_incomplete_base_class)
<< SpecifierRange)) {
diag::err_incomplete_base_class, SpecifierRange)) {
Class->setInvalidDecl();
return 0;
}
@ -10650,8 +10649,8 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
if (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
if (!RT->isBeingDefined() &&
RequireCompleteType(New->getLocation(), NewClassTy,
PDiag(diag::err_covariant_return_incomplete)
<< New->getDeclName()))
diag::err_covariant_return_incomplete,
New->getDeclName()))
return true;
}

View File

@ -474,11 +474,11 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
Diag(SuperLoc, diag::err_undef_superclass)
<< SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
else if (RequireCompleteType(SuperLoc,
Context.getObjCInterfaceType(SuperClassDecl),
PDiag(diag::err_forward_superclass)
<< SuperClassDecl->getDeclName()
<< ClassName
<< SourceRange(AtInterfaceLoc, ClassLoc))) {
Context.getObjCInterfaceType(SuperClassDecl),
diag::err_forward_superclass,
SuperClassDecl->getDeclName(),
ClassName,
SourceRange(AtInterfaceLoc, ClassLoc))) {
SuperClassDecl = 0;
}
}
@ -759,8 +759,8 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
if (!IDecl
|| RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
PDiag(diag::err_category_forward_interface)
<< (CategoryName == 0))) {
diag::err_category_forward_interface,
CategoryName == 0)) {
// Create an invalid ObjCCategoryDecl to serve as context for
// the enclosing method declarations. We mark the decl invalid
// to make it clear that this isn't a valid AST.

View File

@ -51,7 +51,8 @@ bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
// C++ 15.4p2: A type denoted in an exception-specification shall not denote
// an incomplete type.
if (RequireCompleteType(Range.getBegin(), T,
PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range))
diag::err_incomplete_in_exception_spec,
/*direct*/0, Range))
return true;
// C++ 15.4p2: A type denoted in an exception-specification shall not denote
@ -71,8 +72,9 @@ bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) {
if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined())
return false;
if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T,
PDiag(diag::err_incomplete_in_exception_spec) << kind << Range))
if (!T->isVoidType() &&
RequireCompleteType(Range.getBegin(), T,
diag::err_incomplete_in_exception_spec, kind, Range))
return true;
return false;

View File

@ -2838,9 +2838,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
return false;
if (RequireCompleteExprType(E,
PDiag(diag::err_sizeof_alignof_incomplete_type)
<< ExprKind << E->getSourceRange(),
std::make_pair(SourceLocation(), PDiag(0))))
diag::err_sizeof_alignof_incomplete_type,
ExprKind, E->getSourceRange()))
return true;
// Completeing the expression's type may have changed it.
@ -2907,8 +2906,8 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
return false;
if (RequireCompleteType(OpLoc, ExprType,
PDiag(diag::err_sizeof_alignof_incomplete_type)
<< ExprKind << ExprRange))
diag::err_sizeof_alignof_incomplete_type,
ExprKind, ExprRange))
return true;
if (CheckObjCTraitOperandConstraints(*this, ExprType, OpLoc, ExprRange,
@ -3246,8 +3245,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
if (!ResultType.hasQualifiers()) VK = VK_RValue;
} else if (!ResultType->isDependentType() &&
RequireCompleteType(LLoc, ResultType,
PDiag(diag::err_subscript_incomplete_type)
<< BaseExpr->getSourceRange()))
diag::err_subscript_incomplete_type, BaseExpr))
return ExprError();
// Diagnose bad cases where we step over interface counts.
@ -3465,8 +3463,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
if (RequireCompleteType(Arg->getLocStart(),
ProtoArgType,
PDiag(diag::err_call_incomplete_argument)
<< Arg->getSourceRange()))
diag::err_call_incomplete_argument, Arg))
return true;
// Pass the argument
@ -3909,8 +3906,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (RequireCompleteType(Arg->getLocStart(),
Arg->getType(),
PDiag(diag::err_call_incomplete_argument)
<< Arg->getSourceRange()))
diag::err_call_incomplete_argument, Arg))
return ExprError();
TheCall->setArg(i, Arg);
@ -3963,18 +3959,17 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
if (literalType->isArrayType()) {
if (RequireCompleteType(LParenLoc, Context.getBaseElementType(literalType),
PDiag(diag::err_illegal_decl_array_incomplete_type)
<< SourceRange(LParenLoc,
LiteralExpr->getSourceRange().getEnd())))
diag::err_illegal_decl_array_incomplete_type,
SourceRange(LParenLoc,
LiteralExpr->getSourceRange().getEnd())))
return ExprError();
if (literalType->isVariableArrayType())
return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init)
<< SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd()));
} else if (!literalType->isDependentType() &&
RequireCompleteType(LParenLoc, literalType,
PDiag(diag::err_typecheck_decl_incomplete_type)
<< SourceRange(LParenLoc,
LiteralExpr->getSourceRange().getEnd())))
diag::err_typecheck_decl_incomplete_type,
SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())))
return ExprError();
InitializedEntity Entity
@ -6059,8 +6054,8 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
QualType PointeeTy = Operand->getType()->getPointeeType();
if (S.RequireCompleteType(
Loc, PointeeTy,
S.PDiag(diag::err_typecheck_arithmetic_incomplete_type)
<< PointeeTy << Operand->getSourceRange()))
diag::err_typecheck_arithmetic_incomplete_type,
PointeeTy, Operand->getSourceRange()))
return true;
}
return false;
@ -7288,8 +7283,7 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
case Expr::MLV_IncompleteType:
case Expr::MLV_IncompleteVoidType:
return S.RequireCompleteType(Loc, E->getType(),
S.PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue)
<< E->getSourceRange());
diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E);
case Expr::MLV_DuplicateVectorComponents:
Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
break;
@ -8686,8 +8680,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
// with an incomplete type would be ill-formed.
if (!Dependent
&& RequireCompleteType(BuiltinLoc, ArgTy,
PDiag(diag::err_offsetof_incomplete_type)
<< TypeRange))
diag::err_offsetof_incomplete_type, TypeRange))
return ExprError();
// offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
@ -9207,8 +9200,8 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
if (!TInfo->getType()->isDependentType()) {
if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
PDiag(diag::err_second_parameter_to_va_arg_incomplete)
<< TInfo->getTypeLoc().getSourceRange()))
diag::err_second_parameter_to_va_arg_incomplete,
TInfo->getTypeLoc()))
return ExprError();
if (RequireNonAbstractType(TInfo->getTypeLoc().getBeginLoc(),
@ -10670,18 +10663,30 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
return false;
}
PartialDiagnostic Note =
FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here)
<< FD->getDeclName() : PDiag();
SourceLocation NoteLoc = FD ? FD->getLocation() : SourceLocation();
if (RequireCompleteType(Loc, ReturnType,
FD ?
PDiag(diag::err_call_function_incomplete_return)
<< CE->getSourceRange() << FD->getDeclName() :
PDiag(diag::err_call_incomplete_return)
<< CE->getSourceRange(),
std::make_pair(NoteLoc, Note)))
class CallReturnIncompleteDiagnoser : public IncompleteTypeDiagnoser {
FunctionDecl *FD;
CallExpr *CE;
public:
CallReturnIncompleteDiagnoser(FunctionDecl *FD, CallExpr *CE)
: FD(FD), CE(CE) { }
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
if (!FD) {
S.Diag(Loc, diag::err_call_incomplete_return)
<< T << CE->getSourceRange();
return;
}
S.Diag(Loc, diag::err_call_function_incomplete_return)
<< CE->getSourceRange() << FD->getDeclName() << T;
S.Diag(FD->getLocation(),
diag::note_function_with_incomplete_return_type_declared_here)
<< FD->getDeclName();
}
} Diagnoser(FD, CE);
if (RequireCompleteType(Loc, ReturnType, Diagnoser))
return true;
return false;

View File

@ -584,9 +584,9 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
}
if (!isPointer || !Ty->isVoidType()) {
if (RequireCompleteType(ThrowLoc, Ty,
PDiag(isPointer ? diag::err_throw_incomplete_ptr
: diag::err_throw_incomplete)
<< E->getSourceRange()))
isPointer? diag::err_throw_incomplete_ptr
: diag::err_throw_incomplete,
E->getSourceRange()))
return ExprError();
if (RequireNonAbstractType(ThrowLoc, E->getType(),
@ -839,8 +839,7 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
if (!Ty->isVoidType() &&
RequireCompleteType(TyBeginLoc, ElemTy,
PDiag(diag::err_invalid_incomplete_type_use)
<< FullRange))
diag::err_invalid_incomplete_type_use, FullRange))
return ExprError();
if (RequireNonAbstractType(TyBeginLoc, Ty,
@ -1401,9 +1400,7 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc,
return Diag(Loc, diag::err_bad_new_type)
<< AllocType << 1 << R;
else if (!AllocType->isDependentType() &&
RequireCompleteType(Loc, AllocType,
PDiag(diag::err_new_incomplete_type)
<< R))
RequireCompleteType(Loc, AllocType, diag::err_new_incomplete_type,R))
return true;
else if (RequireNonAbstractType(Loc, AllocType,
diag::err_allocation_of_abstract_type))
@ -2014,7 +2011,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
if (const RecordType *Record = Type->getAs<RecordType>()) {
if (RequireCompleteType(StartLoc, Type,
PDiag(diag::err_delete_incomplete_class_type)))
diag::err_delete_incomplete_class_type))
return ExprError();
SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;
@ -2084,8 +2081,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
<< Type << Ex.get()->getSourceRange());
} else if (!Pointee->isDependentType()) {
if (!RequireCompleteType(StartLoc, Pointee,
PDiag(diag::warn_delete_incomplete)
<< Ex.get()->getSourceRange())) {
diag::warn_delete_incomplete, Ex.get())) {
if (const RecordType *RT = PointeeElem->getAs<RecordType>())
PointeeRD = cast<CXXRecordDecl>(RT->getDecl());
}
@ -3767,8 +3763,8 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
if (!Context.hasSameUnqualifiedType(Class, LHSType)) {
// If we want to check the hierarchy, we need a complete type.
if (RequireCompleteType(Loc, LHSType, PDiag(diag::err_bad_memptr_lhs)
<< OpSpelling << (int)isIndirect)) {
if (RequireCompleteType(Loc, LHSType, diag::err_bad_memptr_lhs,
OpSpelling, (int)isIndirect)) {
return QualType();
}
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
@ -4833,8 +4829,7 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
// the member function body.
if (!BaseType->isDependentType() &&
!isThisOutsideMemberFunctionBody(BaseType) &&
RequireCompleteType(OpLoc, BaseType,
PDiag(diag::err_incomplete_member_access)))
RequireCompleteType(OpLoc, BaseType, diag::err_incomplete_member_access))
return ExprError();
// C++ [basic.lookup.classref]p2:

View File

@ -548,8 +548,8 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
RecordDecl *RDecl = RTy->getDecl();
if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
<< BaseRange))
diag::err_typecheck_incomplete_tag,
BaseRange))
return true;
if (HasTemplateArgs) {
@ -1150,9 +1150,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
goto fail;
}
if (RequireCompleteType(OpLoc, BaseType,
PDiag(diag::err_typecheck_incomplete_tag)
<< BaseExpr.get()->getSourceRange()))
if (RequireCompleteType(OpLoc, BaseType, diag::err_typecheck_incomplete_tag,
BaseExpr.get()))
return ExprError();
ObjCInterfaceDecl *ClassDeclared = 0;

View File

@ -910,8 +910,8 @@ ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
if (!EncodedType->getAsArrayTypeUnsafe() && //// Incomplete array is handled.
!EncodedType->isVoidType()) // void is handled too.
if (RequireCompleteType(AtLoc, EncodedType,
PDiag(diag::err_incomplete_type_objc_at_encode)
<< EncodedTypeInfo->getTypeLoc().getSourceRange()))
diag::err_incomplete_type_objc_at_encode,
EncodedTypeInfo->getTypeLoc()))
return ExprError();
std::string Str;
@ -1176,8 +1176,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
param->getType(),
PDiag(diag::err_call_incomplete_argument)
<< argExpr->getSourceRange()))
diag::err_call_incomplete_argument, argExpr))
return true;
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
@ -1395,8 +1394,8 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
SourceRange BaseRange = Super? SourceRange(SuperLoc)
: BaseExpr->getSourceRange();
if (RequireCompleteType(MemberLoc, OPT->getPointeeType(),
PDiag(diag::err_property_not_found_forward_class)
<< MemberName << BaseRange))
diag::err_property_not_found_forward_class,
MemberName, BaseRange))
return ExprError();
// Search for a declared property first.
@ -1524,8 +1523,8 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
if (const ObjCObjectPointerType * OBJPT =
T->getAsObjCInterfacePointerType()) {
if (RequireCompleteType(MemberLoc, OBJPT->getPointeeType(),
PDiag(diag::err_property_not_as_forward_class)
<< MemberName << BaseExpr->getSourceRange()))
diag::err_property_not_as_forward_class,
MemberName, BaseExpr))
return ExprError();
}
Diag(MemberLoc,
@ -1958,11 +1957,11 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
SourceRange TypeRange
= SuperLoc.isValid()? SourceRange(SuperLoc)
: ReceiverTypeInfo->getTypeLoc().getSourceRange();
if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class),
if (RequireCompleteType(Loc, Context.getObjCInterfaceType(Class),
(getLangOpts().ObjCAutoRefCount
? PDiag(diag::err_arc_receiver_forward_class)
: PDiag(diag::warn_receiver_forward_class))
<< TypeRange)) {
? diag::err_arc_receiver_forward_class
: diag::warn_receiver_forward_class),
TypeRange)) {
// A forward class used in messaging is treated as a 'Class'
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LBracLoc, RBracLoc));
@ -2221,12 +2220,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
const ObjCInterfaceDecl *forwardClass = 0;
if (RequireCompleteType(Loc, OCIType->getPointeeType(),
getLangOpts().ObjCAutoRefCount
? PDiag(diag::err_arc_receiver_forward_instance)
<< (Receiver ? Receiver->getSourceRange()
: SourceRange(SuperLoc))
: PDiag(diag::warn_receiver_forward_instance)
<< (Receiver ? Receiver->getSourceRange()
: SourceRange(SuperLoc)))) {
? diag::err_arc_receiver_forward_instance
: diag::warn_receiver_forward_instance,
Receiver? Receiver->getSourceRange()
: SourceRange(SuperLoc))) {
if (getLangOpts().ObjCAutoRefCount)
return ExprError();

View File

@ -3108,7 +3108,7 @@ static void TryListInitialization(Sema &S,
return;
}
if (DestType->isRecordType()) {
if (S.RequireCompleteType(InitList->getLocStart(), DestType, S.PDiag())) {
if (S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) {
Sequence.setIncompleteTypeFailure(DestType);
return;
}
@ -4452,7 +4452,7 @@ static ExprResult CopyObject(Sema &S,
SourceLocation Loc = getInitializationLoc(Entity, CurInit.get());
// Make sure that the type we are copying is complete.
if (S.RequireCompleteType(Loc, T, S.PDiag(diag::err_temp_copy_incomplete)))
if (S.RequireCompleteType(Loc, T, diag::err_temp_copy_incomplete))
return move(CurInit);
// Perform overload resolution using the class's copy/move constructors.
@ -4516,7 +4516,7 @@ static ExprResult CopyObject(Sema &S,
for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) {
ParmVarDecl *Parm = Constructor->getParamDecl(I);
if (S.RequireCompleteType(Loc, Parm->getType(),
S.PDiag(diag::err_call_incomplete_argument)))
diag::err_call_incomplete_argument))
break;
// Build the default argument expression; we don't actually care

View File

@ -670,8 +670,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
QualType PropertyIvarType = PropType.getNonReferenceType();
if (RequireCompleteType(PropertyDiagLoc, PropertyIvarType,
PDiag(diag::err_incomplete_synthesized_property)
<< property->getDeclName())) {
diag::err_incomplete_synthesized_property,
property->getDeclName())) {
Diag(property->getLocation(), diag::note_property_declare);
CompleteTypeErr = true;
}

View File

@ -1657,7 +1657,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, PDiag()))
!RequireCompleteType(From->getLocStart(), FromType, 0))
return Context.hasSameUnqualifiedType(ToType,
FromEnumType->getDecl()->getPromotionType());
}
@ -1987,7 +1987,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
if (getLangOpts().CPlusPlus &&
FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
!Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) &&
!RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) &&
!RequireCompleteType(From->getLocStart(), FromPointeeType, 0) &&
IsDerivedFrom(FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
@ -2616,7 +2616,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
QualType ToClass(ToTypePtr->getClass(), 0);
if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
!RequireCompleteType(From->getLocStart(), ToClass, PDiag()) &&
!RequireCompleteType(From->getLocStart(), ToClass, 0) &&
IsDerivedFrom(ToClass, FromClass)) {
ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
ToClass.getTypePtr());
@ -2923,7 +2923,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
S.IsDerivedFrom(From->getType(), ToType)))
ConstructorsOnly = true;
S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag());
S.RequireCompleteType(From->getLocStart(), ToType, 0);
// RequireCompleteType may have returned true due to some invalid decl
// during template instantiation, but ToType may be complete enough now
// to try to recover.
@ -3001,8 +3001,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(),
S.PDiag(0) << From->getSourceRange())) {
} else if (S.RequireCompleteType(From->getLocStart(), From->getType(), 0)) {
// No conversion functions from incomplete types.
} else if (const RecordType *FromRecordType
= From->getType()->getAs<RecordType>()) {
@ -3848,7 +3847,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
ObjCLifetimeConversion = false;
if (UnqualT1 == UnqualT2) {
// Nothing to do.
} else if (!RequireCompleteType(Loc, OrigT2, PDiag()) &&
} else if (!RequireCompleteType(Loc, OrigT2, 0) &&
IsDerivedFrom(UnqualT2, UnqualT1))
DerivedToBase = true;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
@ -4313,7 +4312,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, S.PDiag()))
if (S.RequireCompleteType(From->getLocStart(), ToType, 0))
return Result;
// C++11 [over.ics.list]p2:
@ -5062,7 +5061,18 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
}
// We must have a complete class type.
if (RequireCompleteType(Loc, T, IncompleteDiag))
struct IncompleteTypeDiagnoserPartialDiag : IncompleteTypeDiagnoser {
const PartialDiagnostic &PD;
IncompleteTypeDiagnoserPartialDiag(const PartialDiagnostic &PD)
: IncompleteTypeDiagnoser(PD.getDiagID() == 0), PD(PD) {}
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
S.Diag(Loc, PD) << T;
}
} IncompleteDiagnoser(IncompleteDiag);
if (RequireCompleteType(Loc, T, IncompleteDiagnoser))
return Owned(From);
// Look for a conversion to an integral or enumeration type.
@ -5906,7 +5916,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
// empty.
if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
// Complete the type if it can be completed. Otherwise, we're done.
if (RequireCompleteType(OpLoc, T1, PDiag()))
if (RequireCompleteType(OpLoc, T1, 0))
return;
LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName);
@ -10610,8 +10620,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
if (RequireCompleteType(LParenLoc, Object.get()->getType(),
PDiag(diag::err_incomplete_object_call)
<< Object.get()->getSourceRange()))
diag::err_incomplete_object_call, Object.get()))
return true;
LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
@ -10899,8 +10908,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
if (RequireCompleteType(Loc, Base->getType(),
PDiag(diag::err_typecheck_incomplete_tag)
<< Base->getSourceRange()))
diag::err_typecheck_incomplete_tag, Base))
return ExprError();
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);

View File

@ -889,8 +889,7 @@ Sema::ObjCSubscriptKind
// We must have a complete class type.
if (RequireCompleteType(FromE->getExprLoc(), T,
PDiag(diag::err_objc_index_incomplete_class_type)
<< FromE->getSourceRange()))
diag::err_objc_index_incomplete_class_type, FromE))
return OS_Error;
// Look for a conversion to an integral, enumeration type, or

View File

@ -1350,9 +1350,9 @@ Sema::ActOnObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
if (iface &&
RequireCompleteType(forLoc, QualType(objectType, 0),
getLangOpts().ObjCAutoRefCount
? PDiag(diag::err_arc_collection_forward)
<< collection->getSourceRange()
: PDiag(0))) {
? diag::err_arc_collection_forward
: 0,
collection)) {
// Otherwise, if we have any useful type information, check that
// the type declares the appropriate method.
} else if (iface || !objectType->qual_empty()) {
@ -1659,7 +1659,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
QualType RangeType = Range->getType();
if (RequireCompleteType(RangeLoc, RangeType,
PDiag(diag::err_for_range_incomplete_type)))
diag::err_for_range_incomplete_type))
return StmtError();
// Build auto __begin = begin-expr, __end = end-expr.

View File

@ -2825,9 +2825,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
QualType PointeeType = ParamRefType->getPointeeType();
// If the argument has incomplete array type, try to complete it's type.
if (ArgType->isIncompleteArrayType() &&
!S.RequireCompleteExprType(Arg, S.PDiag(),
std::make_pair(SourceLocation(), S.PDiag())))
if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
ArgType = Arg->getType();
// [C++0x] If P is an rvalue reference to a cv-unqualified

View File

@ -4043,14 +4043,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
/// case of a reference type, the referred-to type).
///
/// \param E The expression whose type is required to be complete.
/// \param PD The partial diagnostic that will be printed out if the type cannot
/// be completed.
/// \param Diagnoser The object that will emit a diagnostic if the type is
/// incomplete.
///
/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
/// otherwise.
bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
std::pair<SourceLocation,
PartialDiagnostic> Note) {
bool Sema::RequireCompleteExprType(Expr *E, IncompleteTypeDiagnoser &Diagnoser){
QualType T = E->getType();
// Fast path the case where the type is already complete.
@ -4107,7 +4105,26 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
if (const ReferenceType *Ref = T->getAs<ReferenceType>())
T = Ref->getPointeeType();
return RequireCompleteType(E->getExprLoc(), T, PD, Note);
return RequireCompleteType(E->getExprLoc(), T, Diagnoser);
}
namespace {
struct IncompleteTypeDiagnoserDiag : Sema::IncompleteTypeDiagnoser {
unsigned DiagID;
IncompleteTypeDiagnoserDiag(unsigned DiagID)
: Sema::IncompleteTypeDiagnoser(DiagID == 0), DiagID(DiagID) {}
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
if (Suppressed) return;
S.Diag(Loc, DiagID) << T;
}
};
}
bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
IncompleteTypeDiagnoserDiag Diagnoser(DiagID);
return RequireCompleteExprType(E, Diagnoser);
}
/// @brief Ensure that the type T is a complete type.
@ -4131,11 +4148,7 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
/// @returns @c true if @p T is incomplete and a diagnostic was emitted,
/// @c false otherwise.
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
const PartialDiagnostic &PD,
std::pair<SourceLocation,
PartialDiagnostic> Note) {
unsigned diag = PD.getDiagID();
IncompleteTypeDiagnoser &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
@ -4148,7 +4161,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
NamedDecl *Def = 0;
if (!T->isIncompleteType(&Def)) {
// If we know about the definition but it is not visible, complain.
if (diag != 0 && Def && !LookupResult::isVisible(Def)) {
if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(Def)) {
// Suppress this error outside of a SFINAE context if we've already
// emitted the error once for this type. There's no usefulness in
// repeating the diagnostic.
@ -4204,7 +4217,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
/*Complain=*/!Diagnoser.Suppressed);
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
@ -4216,20 +4229,16 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
return InstantiateClass(Loc, Rec, Pattern,
getTemplateInstantiationArgs(Rec),
TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
/*Complain=*/!Diagnoser.Suppressed);
}
}
}
if (diag == 0)
if (Diagnoser.Suppressed)
return true;
// We have an incomplete type. Produce a diagnostic.
Diag(Loc, PD) << T;
// If we have a note, produce it.
if (!Note.first.isInvalid())
Diag(Note.first, Note.second);
Diagnoser.diagnose(*this, Loc, T);
// If the type was a forward declaration of a class/struct/union
// type, produce a note.
@ -4247,15 +4256,9 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
}
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
const PartialDiagnostic &PD) {
return RequireCompleteType(Loc, T, PD,
std::make_pair(SourceLocation(), PDiag(0)));
}
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID) {
return RequireCompleteType(Loc, T, PDiag(DiagID),
std::make_pair(SourceLocation(), PDiag(0)));
unsigned DiagID) {
IncompleteTypeDiagnoserDiag Diagnoser(DiagID);
return RequireCompleteType(Loc, T, Diagnoser);
}
/// @brief Ensure that the type T is a literal type.
@ -4305,8 +4308,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
// class type must have a trivial destructor (which can't be checked until
// the class definition is complete).
if (!RD->isCompleteDefinition()) {
RequireCompleteType(Loc, ElemType,
PDiag(diag::note_non_literal_incomplete) << T);
RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T);
return true;
}
@ -4487,8 +4489,7 @@ QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
if (!T->isDependentType()) {
// FIXME: It isn't entirely clear whether incomplete atomic types
// are allowed or not; for simplicity, ban them for the moment.
if (RequireCompleteType(Loc, T,
PDiag(diag::err_atomic_specifier_bad_type) << 0))
if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0))
return QualType();
int DisallowedKind = -1;