From d10099e5c8238fa0327f03921cf2e3c8975c881e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 4 May 2012 16:32:21 +0000 Subject: [PATCH] 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156176 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 138 +++++++++++++++++++++++++++-- lib/Sema/SemaCXXScopeSpec.cpp | 5 +- lib/Sema/SemaCast.cpp | 12 +-- lib/Sema/SemaChecking.cpp | 2 +- lib/Sema/SemaDeclCXX.cpp | 7 +- lib/Sema/SemaDeclObjC.cpp | 14 +-- lib/Sema/SemaExceptionSpec.cpp | 8 +- lib/Sema/SemaExpr.cpp | 79 +++++++++-------- lib/Sema/SemaExprCXX.cpp | 25 +++--- lib/Sema/SemaExprMember.cpp | 9 +- lib/Sema/SemaExprObjC.cpp | 33 ++++--- lib/Sema/SemaInit.cpp | 6 +- lib/Sema/SemaObjCProperty.cpp | 4 +- lib/Sema/SemaOverload.cpp | 36 +++++--- lib/Sema/SemaPseudoObject.cpp | 3 +- lib/Sema/SemaStmt.cpp | 8 +- lib/Sema/SemaTemplateDeduction.cpp | 4 +- lib/Sema/SemaType.cpp | 69 ++++++++------- 18 files changed, 294 insertions(+), 168 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 549c32bf9c..e300a858e0 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 + 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 + 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 + 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 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 Note); + + template + bool RequireCompleteType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1) { + BoundIncompleteTypeDiagnoser1 Diagnoser(DiagID, Arg1); + return RequireCompleteType(Loc, T, Diagnoser); + } + + template + bool RequireCompleteType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1, const T2 &Arg2) { + BoundIncompleteTypeDiagnoser2 Diagnoser(DiagID, Arg1, Arg2); + return RequireCompleteType(Loc, T, Diagnoser); + } + + template + bool RequireCompleteType(SourceLocation Loc, QualType T, + unsigned DiagID, const T1 &Arg1, const T2 &Arg2, + const T3 &Arg3) { + BoundIncompleteTypeDiagnoser3 Diagnoser(DiagID, Arg1, Arg2, + Arg3); + return RequireCompleteType(Loc, T, Diagnoser); + } + + bool RequireCompleteExprType(Expr *E, IncompleteTypeDiagnoser &Diagnoser); + bool RequireCompleteExprType(Expr *E, unsigned DiagID); + + template + bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1) { + BoundIncompleteTypeDiagnoser1 Diagnoser(DiagID, Arg1); + return RequireCompleteExprType(E, Diagnoser); + } + + template + bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1, + const T2 &Arg2) { + BoundIncompleteTypeDiagnoser2 Diagnoser(DiagID, Arg1, Arg2); + return RequireCompleteExprType(E, Diagnoser); + } + + template + bool RequireCompleteExprType(Expr *E, unsigned DiagID, const T1 &Arg1, + const T2 &Arg2, const T3 &Arg3) { + BoundIncompleteTypeDiagnoser3 Diagnoser(DiagID, Arg1, Arg2, + Arg3); + return RequireCompleteExprType(E, Diagnoser); + } bool RequireLiteralType(SourceLocation Loc, QualType T, const PartialDiagnostic &PD); diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 3a884a95a1..0de9dd5f64 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -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; } diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index a67d1dec59..c11c30aa17 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -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(); 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. diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 0c8309e58e..4504a6a1e1 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -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; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6bae2e6a25..5e466adc5f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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()) { if (!RT->isBeingDefined() && RequireCompleteType(New->getLocation(), NewClassTy, - PDiag(diag::err_covariant_return_incomplete) - << New->getDeclName())) + diag::err_covariant_return_incomplete, + New->getDeclName())) return true; } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 1b4896b505..d2fdd4fec6 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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. diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index ec33f0ac8e..f88ead56f4 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -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()->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; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 90435aace7..ce4bffa1cb 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index af0f971c1c..88c2bf408d 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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()) { if (RequireCompleteType(StartLoc, Type, - PDiag(diag::err_delete_incomplete_class_type))) + diag::err_delete_incomplete_class_type)) return ExprError(); SmallVector 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()) PointeeRD = cast(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: diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 7532cb4485..6af4040784 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -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; diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index b45b7c92ce..ed71eb128c 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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(); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 7d88c7eea9..0ef1b1e81f 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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 diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 9f9c96046a..be0de14fd3 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -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; } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index ea7e0e8a80..a3a963f356 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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(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()) { @@ -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()) { // 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(); 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); diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index 0e6632964a..5e44c9bb8b 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -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 diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 2d03ab99ef..407323d5fa 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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. diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index d68e4642fc..e6f2b2d649 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -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 diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index f857218b50..c81ace1287 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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 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()) 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 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(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; -- 2.40.0