From: Douglas Gregor Date: Tue, 22 Dec 2009 01:01:55 +0000 (+0000) Subject: Centralize the emission/suppression/delay of diagnostics describing runtime before... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1c7c3fb2641812fdf31b3f80f995116b02ac7863;p=clang Centralize the emission/suppression/delay of diagnostics describing runtime before in the new function Sema::DiagRuntimeBehavior, addressing one of Chris' comments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91870 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 35fee3d866..97907198b1 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1437,7 +1437,8 @@ public: virtual void PopExpressionEvaluationContext(); void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); - + bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD); + // Primary Expressions. virtual SourceRange getExprRange(ExprTy *E) const; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f8afd0f33e..d45179e94c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -259,44 +259,17 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) { bool Sema::DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT) { DefaultArgumentPromotion(Expr); - if (Expr->getType()->isObjCInterfaceType()) { - switch (ExprEvalContexts.back().Context ) { - case Unevaluated: - // The argument will never be evaluated, so don't complain. - break; - - case PotentiallyEvaluated: - Diag(Expr->getLocStart(), - diag::err_cannot_pass_objc_interface_to_vararg) - << Expr->getType() << CT; - return true; - - case PotentiallyPotentiallyEvaluated: - ExprEvalContexts.back().addDiagnostic(Expr->getLocStart(), - PDiag(diag::err_cannot_pass_objc_interface_to_vararg) - << Expr->getType() << CT); - break; - } - } - - if (!Expr->getType()->isPODType()) { - switch (ExprEvalContexts.back().Context ) { - case Unevaluated: - // The argument will never be evaluated, so don't complain. - break; - - case PotentiallyEvaluated: - Diag(Expr->getLocStart(), diag::warn_cannot_pass_non_pod_arg_to_vararg) - << Expr->getType() << CT; - break; + if (Expr->getType()->isObjCInterfaceType() && + DiagRuntimeBehavior(Expr->getLocStart(), + PDiag(diag::err_cannot_pass_objc_interface_to_vararg) + << Expr->getType() << CT)) + return true; - case PotentiallyPotentiallyEvaluated: - ExprEvalContexts.back().addDiagnostic(Expr->getLocStart(), - PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << Expr->getType() << CT); - break; - } - } + if (!Expr->getType()->isPODType() && + DiagRuntimeBehavior(Expr->getLocStart(), + PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) + << Expr->getType() << CT)) + return true; return false; } @@ -6436,28 +6409,12 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, // Get the decl corresponding to this. RecordDecl *RD = RC->getDecl(); if (CXXRecordDecl *CRD = dyn_cast(RD)) { - if (!CRD->isPOD() && !DidWarnAboutNonPOD) { - switch (ExprEvalContexts.back().Context ) { - case Unevaluated: - // The argument will never be evaluated, so don't complain. - break; - - case PotentiallyEvaluated: - ExprError(Diag(BuiltinLoc, diag::warn_offsetof_non_pod_type) - << SourceRange(CompPtr[0].LocStart, OC.LocEnd) - << Res->getType()); - DidWarnAboutNonPOD = true; - break; - - case PotentiallyPotentiallyEvaluated: - ExprEvalContexts.back().addDiagnostic(BuiltinLoc, - PDiag(diag::warn_offsetof_non_pod_type) - << SourceRange(CompPtr[0].LocStart, OC.LocEnd) - << Res->getType()); - DidWarnAboutNonPOD = true; - break; - } - } + if (!CRD->isPOD() && !DidWarnAboutNonPOD && + DiagRuntimeBehavior(BuiltinLoc, + PDiag(diag::warn_offsetof_non_pod_type) + << SourceRange(CompPtr[0].LocStart, OC.LocEnd) + << Res->getType())) + DidWarnAboutNonPOD = true; } LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); @@ -7078,6 +7035,41 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } } +/// \brief Emit a diagnostic that describes an effect on the run-time behavior +/// of the program being compiled. +/// +/// This routine emits the given diagnostic when the code currently being +/// type-checked is "potentially evaluated", meaning that there is a +/// possibility that the code will actually be executable. Code in sizeof() +/// expressions, code used only during overload resolution, etc., are not +/// potentially evaluated. This routine will suppress such diagnostics or, +/// in the absolutely nutty case of potentially potentially evaluated +/// expressions (C++ typeid), queue the diagnostic to potentially emit it +/// later. +/// +/// This routine should be used for all diagnostics that describe the run-time +/// behavior of a program, such as passing a non-POD value through an ellipsis. +/// Failure to do so will likely result in spurious diagnostics or failures +/// during overload resolution or within sizeof/alignof/typeof/typeid. +bool Sema::DiagRuntimeBehavior(SourceLocation Loc, + const PartialDiagnostic &PD) { + switch (ExprEvalContexts.back().Context ) { + case Unevaluated: + // The argument will never be evaluated, so don't complain. + break; + + case PotentiallyEvaluated: + Diag(Loc, PD); + return true; + + case PotentiallyPotentiallyEvaluated: + ExprEvalContexts.back().addDiagnostic(Loc, PD); + break; + } + + return false; +} + bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, CallExpr *CE, FunctionDecl *FD) { if (ReturnType->isVoidType() || !ReturnType->isIncompleteType())