Add the diagnose_if attribute to clang.
`diagnose_if` can be used to have clang emit either warnings or errors
for function calls that meet user-specified conditions. For example:
```
constexpr int foo(int a)
__attribute__((diagnose_if(a > 10, "configurations with a > 10 are "
"expensive.", "warning")));
int f1 = foo(9);
int f2 = foo(10); // warning: configuration with a > 10 are expensive.
int f3 = foo(f2);
```
It currently only emits diagnostics in cases where the condition is
guaranteed to always be true. So, the following code will emit no
warnings:
```
constexpr int bar(int a) {
foo(a);
return 0;
}
constexpr int i = bar(10);
```
We hope to support optionally emitting diagnostics for cases like that
(and emitting runtime checks) in the future.
Release notes will appear shortly. :)
Differential Revision: https://reviews.llvm.org/D27424
llvm-svn: 291418
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 18206e5..fe77c7f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10410,10 +10410,25 @@
bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
const FunctionDecl *Callee,
- ArrayRef<const Expr*> Args) const {
+ ArrayRef<const Expr*> Args,
+ const Expr *This) const {
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated);
+ LValue ThisVal;
+ const LValue *ThisPtr = nullptr;
+ if (This) {
+#ifndef NDEBUG
+ auto *MD = dyn_cast<CXXMethodDecl>(Callee);
+ assert(MD && "Don't provide `this` for non-methods.");
+ assert(!MD->isStatic() && "Don't provide `this` for static methods.");
+#endif
+ if (EvaluateObjectArgument(Info, This, ThisVal))
+ ThisPtr = &ThisVal;
+ if (Info.EvalStatus.HasSideEffects)
+ return false;
+ }
+
ArgVector ArgValues(Args.size());
for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end();
I != E; ++I) {
@@ -10426,7 +10441,7 @@
}
// Build fake call to Callee.
- CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/nullptr,
+ CallStackFrame Frame(Info, Callee->getLocation(), Callee, ThisPtr,
ArgValues.data());
return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects;
}