Change how we handle diagnose_if attributes.
This patch changes how we handle argument-dependent `diagnose_if`
attributes. In particular, we now check them in the same place that we
check for things like passing NULL to Nonnull args, etc. This is
basically better in every way than how we were handling them before. :)
This fixes PR31638, PR31639, and PR31640.
Differential Revision: https://reviews.llvm.org/D28889
llvm-svn: 293360
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 49208e2..3aedb2a 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2426,11 +2426,12 @@
}
/// Handles the checks for format strings, non-POD arguments to vararg
-/// functions, and NULL arguments passed to non-NULL parameters.
+/// functions, NULL arguments passed to non-NULL parameters, and diagnose_if
+/// attributes.
void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
- ArrayRef<const Expr *> Args, bool IsMemberFunction,
- SourceLocation Loc, SourceRange Range,
- VariadicCallType CallType) {
+ const Expr *ThisArg, ArrayRef<const Expr *> Args,
+ bool IsMemberFunction, SourceLocation Loc,
+ SourceRange Range, VariadicCallType CallType) {
// FIXME: We should check as much as we can in the template definition.
if (CurContext->isDependentContext())
return;
@@ -2477,6 +2478,9 @@
CheckArgumentWithTypeTag(I, Args.data());
}
}
+
+ if (FD)
+ diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
}
/// CheckConstructorCall - Check a constructor call for correctness and safety
@@ -2487,8 +2491,8 @@
SourceLocation Loc) {
VariadicCallType CallType =
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
- checkCall(FDecl, Proto, Args, /*IsMemberFunction=*/true, Loc, SourceRange(),
- CallType);
+ checkCall(FDecl, Proto, /*ThisArg=*/nullptr, Args, /*IsMemberFunction=*/true,
+ Loc, SourceRange(), CallType);
}
/// CheckFunctionCall - Check a direct function call for various correctness
@@ -2503,14 +2507,20 @@
TheCall->getCallee());
Expr** Args = TheCall->getArgs();
unsigned NumArgs = TheCall->getNumArgs();
+
+ Expr *ImplicitThis = nullptr;
if (IsMemberOperatorCall) {
// If this is a call to a member operator, hide the first argument
// from checkCall.
// FIXME: Our choice of AST representation here is less than ideal.
+ ImplicitThis = Args[0];
++Args;
--NumArgs;
- }
- checkCall(FDecl, Proto, llvm::makeArrayRef(Args, NumArgs),
+ } else if (IsMemberFunction)
+ ImplicitThis =
+ cast<CXXMemberCallExpr>(TheCall)->getImplicitObjectArgument();
+
+ checkCall(FDecl, Proto, ImplicitThis, llvm::makeArrayRef(Args, NumArgs),
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -2546,8 +2556,8 @@
VariadicCallType CallType =
Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply;
- checkCall(Method, nullptr, Args,
- /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
+ checkCall(Method, nullptr, /*ThisArg=*/nullptr, Args,
+ /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(),
CallType);
return false;
@@ -2576,7 +2586,7 @@
CallType = VariadicFunction;
}
- checkCall(NDecl, Proto,
+ checkCall(NDecl, Proto, /*ThisArg=*/nullptr,
llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
/*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -2589,7 +2599,7 @@
bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto,
TheCall->getCallee());
- checkCall(/*FDecl=*/nullptr, Proto,
+ checkCall(/*FDecl=*/nullptr, Proto, /*ThisArg=*/nullptr,
llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
/*IsMemberFunction=*/false, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);