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;
 }