For DR712: store on a DeclRefExpr whether it constitutes an odr-use.

Begin restructuring to support the forms of non-odr-use reference
permitted by DR712.

llvm-svn: 363086
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 61f9de9..db18ac4 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1783,8 +1783,8 @@
   }
 
   llvm::Constant *constant = nullptr;
-  if (emission.IsConstantAggregate || D.isConstexpr() ||
-      D.isUsableInConstantExpressions(getContext())) {
+  if (emission.IsConstantAggregate ||
+      D.mightBeUsableInConstantExpressions(getContext())) {
     assert(!capturedByInit && "constant init contains a capturing block?");
     constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
     if (constant && !constant->isZeroValue() &&
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 5b57655..46b1af5 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1398,7 +1398,7 @@
 
 /// Can we constant-emit a load of a reference to a variable of the
 /// given type?  This is different from predicates like
-/// Decl::isUsableInConstantExpressions because we do want it to apply
+/// Decl::mightBeUsableInConstantExpressions because we do want it to apply
 /// in situations that don't necessarily satisfy the language's rules
 /// for this (e.g. C++'s ODR-use rules).  For example, we want to able
 /// to do this with const float variables even if those variables
@@ -1492,11 +1492,17 @@
 static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF,
                                                         const MemberExpr *ME) {
   if (auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
+    // FIXME: Copy this from the MemberExpr once we store it there.
+    NonOdrUseReason NOUR = NOUR_None;
+    if (VD->getType()->isReferenceType() &&
+        VD->isUsableInConstantExpressions(CGF.getContext()))
+      NOUR = NOUR_Constant;
+
     // Try to emit static variable member expressions as DREs.
     return DeclRefExpr::Create(
         CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
         /*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(),
-        ME->getType(), ME->getValueKind());
+        ME->getType(), ME->getValueKind(), nullptr, nullptr, NOUR);
   }
   return nullptr;
 }
@@ -2462,12 +2468,11 @@
 
     // A DeclRefExpr for a reference initialized by a constant expression can
     // appear without being odr-used. Directly emit the constant initializer.
-    const Expr *Init = VD->getAnyInitializer(VD);
+    VD->getAnyInitializer(VD);
     const auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl);
-    if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() &&
-        VD->isUsableInConstantExpressions(getContext()) &&
-        VD->checkInitIsICE() &&
+    if (E->isNonOdrUse() == NOUR_Constant && VD->getType()->isReferenceType() &&
         // Do not emit if it is private OpenMP variable.
+        // FIXME: This should be handled in odr-use marking, not here.
         !(E->refersToEnclosingVariableOrCapture() &&
           ((CapturedStmtInfo &&
             (LocalDeclMap.count(VD->getCanonicalDecl()) ||
@@ -2489,6 +2494,8 @@
       return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl);
     }
 
+    // FIXME: Handle other kinds of non-odr-use DeclRefExprs.
+
     // Check for captured variables.
     if (E->refersToEnclosingVariableOrCapture()) {
       VD = VD->getCanonicalDecl();