C++11 constexpr: Add note stacks containing backtraces if constant evaluation
fails within a call to a constexpr function. Add -fconstexpr-backtrace-limit
argument to driver and frontend, to control the maximum number of notes so
produced (default 10). Fix APValue printing to be able to pretty-print all
APValue types, and move the testing for this functionality from a unittest to
a -verify test now that it's visible in clang's output.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146749 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index b99a662..0d4dea8 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -12,7 +12,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/raw_ostream.h"
@@ -203,7 +207,7 @@
 }
 
 void APValue::dump() const {
-  print(llvm::errs());
+  dump(llvm::errs());
   llvm::errs() << '\n';
 }
 
@@ -215,7 +219,7 @@
   return V.convertToDouble();
 }
 
-void APValue::print(raw_ostream &OS) const {
+void APValue::dump(raw_ostream &OS) const {
   switch (getKind()) {
   case Uninitialized:
     OS << "Uninitialized";
@@ -227,9 +231,12 @@
     OS << "Float: " << GetApproxValue(getFloat());
     return;
   case Vector:
-    OS << "Vector: " << getVectorElt(0);
-    for (unsigned i = 1; i != getVectorLength(); ++i)
-      OS << ", " << getVectorElt(i);
+    OS << "Vector: ";
+    getVectorElt(0).dump(OS);
+    for (unsigned i = 1; i != getVectorLength(); ++i) {
+      OS << ", ";
+      getVectorElt(i).dump(OS);
+    }
     return;
   case ComplexInt:
     OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
@@ -244,28 +251,36 @@
   case Array:
     OS << "Array: ";
     for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
-      OS << getArrayInitializedElt(I);
+      getArrayInitializedElt(I).dump(OS);
       if (I != getArraySize() - 1) OS << ", ";
     }
-    if (hasArrayFiller())
-      OS << getArraySize() - getArrayInitializedElts() << " x "
-         << getArrayFiller();
+    if (hasArrayFiller()) {
+      OS << getArraySize() - getArrayInitializedElts() << " x ";
+      getArrayFiller().dump(OS);
+    }
     return;
   case Struct:
     OS << "Struct ";
     if (unsigned N = getStructNumBases()) {
-      OS << " bases: " << getStructBase(0);
-      for (unsigned I = 1; I != N; ++I)
-        OS << ", " << getStructBase(I);
+      OS << " bases: ";
+      getStructBase(0).dump(OS);
+      for (unsigned I = 1; I != N; ++I) {
+        OS << ", ";
+        getStructBase(I).dump(OS);
+      }
     }
     if (unsigned N = getStructNumFields()) {
-      OS << " fields: " << getStructField(0);
-      for (unsigned I = 1; I != N; ++I)
-        OS << ", " << getStructField(I);
+      OS << " fields: ";
+      getStructField(0).dump(OS);
+      for (unsigned I = 1; I != N; ++I) {
+        OS << ", ";
+        getStructField(I).dump(OS);
+      }
     }
     return;
   case Union:
-    OS << "Union: " << getUnionValue();
+    OS << "Union: ";
+    getUnionValue().dump(OS);
     return;
   case MemberPointer:
     OS << "MemberPointer: <todo>";
@@ -274,78 +289,198 @@
   llvm_unreachable("Unknown APValue kind!");
 }
 
-static void WriteShortAPValueToStream(raw_ostream& Out,
-                                      const APValue& V) {
-  switch (V.getKind()) {
+void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{
+  switch (getKind()) {
   case APValue::Uninitialized:
-    Out << "Uninitialized";
+    Out << "<uninitialized>";
     return;
   case APValue::Int:
-    Out << V.getInt();
+    Out << getInt();
     return;
   case APValue::Float:
-    Out << GetApproxValue(V.getFloat());
+    Out << GetApproxValue(getFloat());
     return;
-  case APValue::Vector:
-    Out << '[';
-    WriteShortAPValueToStream(Out, V.getVectorElt(0));
-    for (unsigned i = 1; i != V.getVectorLength(); ++i) {
+  case APValue::Vector: {
+    Out << '{';
+    QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
+    getVectorElt(0).printPretty(Out, Ctx, ElemTy);
+    for (unsigned i = 1; i != getVectorLength(); ++i) {
       Out << ", ";
-      WriteShortAPValueToStream(Out, V.getVectorElt(i));
+      getVectorElt(i).printPretty(Out, Ctx, ElemTy);
     }
-    Out << ']';
+    Out << '}';
     return;
+  }
   case APValue::ComplexInt:
-    Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
+    Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
     return;
   case APValue::ComplexFloat:
-    Out << GetApproxValue(V.getComplexFloatReal()) << "+"
-        << GetApproxValue(V.getComplexFloatImag()) << "i";
+    Out << GetApproxValue(getComplexFloatReal()) << "+"
+        << GetApproxValue(getComplexFloatImag()) << "i";
     return;
-  case APValue::LValue:
-    Out << "LValue: <todo>";
-    return;
-  case APValue::Array:
-    Out << '{';
-    if (unsigned N = V.getArrayInitializedElts()) {
-      Out << V.getArrayInitializedElt(0);
-      for (unsigned I = 1; I != N; ++I)
-        Out << ", " << V.getArrayInitializedElt(I);
+  case APValue::LValue: {
+    LValueBase Base = getLValueBase();
+    if (!Base) {
+      Out << "0";
+      return;
     }
-    Out << '}';
+
+    bool IsReference = Ty->isReferenceType();
+    QualType InnerTy
+      = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
+
+    if (!hasLValuePath()) {
+      // No lvalue path: just print the offset.
+      CharUnits O = getLValueOffset();
+      CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
+      if (!O.isZero()) {
+        if (IsReference)
+          Out << "*(";
+        if (O % S) {
+          Out << "(char*)";
+          S = CharUnits::One();
+        }
+        Out << '&';
+      } else if (!IsReference)
+        Out << '&';
+
+      if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
+        Out << *VD;
+      else
+        Base.get<const Expr*>()->printPretty(Out, Ctx, 0,
+                                             Ctx.getPrintingPolicy());
+      if (!O.isZero()) {
+        Out << " + " << (O / S);
+        if (IsReference)
+          Out << ')';
+      }
+      return;
+    }
+
+    // We have an lvalue path. Print it out nicely.
+    if (!IsReference)
+      Out << '&';
+    else if (isLValueOnePastTheEnd())
+      Out << "*(&";
+
+    QualType ElemTy;
+    if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
+      Out << *VD;
+      ElemTy = VD->getType();
+    } else {
+      const Expr *E = Base.get<const Expr*>();
+      E->printPretty(Out, Ctx, 0,Ctx.getPrintingPolicy());
+      ElemTy = E->getType();
+    }
+
+    ArrayRef<LValuePathEntry> Path = getLValuePath();
+    const CXXRecordDecl *CastToBase = 0;
+    for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+      if (ElemTy->getAs<RecordType>()) {
+        // The lvalue refers to a class type, so the next path entry is a base
+        // or member.
+        const Decl *BaseOrMember =
+        BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer();
+        if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
+          CastToBase = RD;
+          ElemTy = Ctx.getRecordType(RD);
+        } else {
+          const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
+          Out << ".";
+          if (CastToBase)
+            Out << *CastToBase << "::";
+          Out << *VD;
+          ElemTy = VD->getType();
+        }
+      } else {
+        // The lvalue must refer to an array.
+        Out << '[' << Path[I].ArrayIndex << ']';
+        ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
+      }
+    }
+
+    // Handle formatting of one-past-the-end lvalues.
+    if (isLValueOnePastTheEnd()) {
+      // FIXME: If CastToBase is non-0, we should prefix the output with
+      // "(CastToBase*)".
+      Out << " + 1";
+      if (IsReference)
+        Out << ')';
+    }
     return;
-  case APValue::Struct:
+  }
+  case APValue::Array: {
+    const ArrayType *AT = Ctx.getAsArrayType(Ty);
+    QualType ElemTy = AT->getElementType();
     Out << '{';
-    if (unsigned N = V.getStructNumBases()) {
-      Out << V.getStructBase(0);
-      for (unsigned I = 1; I != N; ++I)
-        Out << ", " << V.getStructBase(I);
-      if (V.getStructNumFields())
+    if (unsigned N = getArrayInitializedElts()) {
+      getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
+      for (unsigned I = 1; I != N; ++I) {
         Out << ", ";
-    }
-    if (unsigned N = V.getStructNumFields()) {
-      Out << V.getStructField(0);
-      for (unsigned I = 1; I != N; ++I)
-        Out << ", " << V.getStructField(I);
+        if (I == 10) {
+          // Avoid printing out the entire contents of large arrays.
+          Out << "...";
+          break;
+        }
+        getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
+      }
     }
     Out << '}';
     return;
+  }
+  case APValue::Struct: {
+    Out << '{';
+    const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
+    bool First = true;
+    if (unsigned N = getStructNumBases()) {
+      const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
+      CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
+      for (unsigned I = 0; I != N; ++I, ++BI) {
+        assert(BI != CD->bases_end());
+        if (!First)
+          Out << ", ";
+        getStructBase(I).printPretty(Out, Ctx, BI->getType());
+        First = false;
+      }
+    }
+    for (RecordDecl::field_iterator FI = RD->field_begin();
+         FI != RD->field_end(); ++FI) {
+      if (!First)
+        Out << ", ";
+      if ((*FI)->isUnnamedBitfield()) continue;
+      getStructField((*FI)->getFieldIndex()).
+        printPretty(Out, Ctx, (*FI)->getType());
+      First = false;
+    }
+    Out << '}';
+    return;
+  }
   case APValue::Union:
-    Out << '{' << V.getUnionValue() << '}';
+    Out << '{';
+    if (const FieldDecl *FD = getUnionField()) {
+      Out << "." << *FD << " = ";
+      getUnionValue().printPretty(Out, Ctx, FD->getType());
+    }
+    Out << '}';
     return;
   case APValue::MemberPointer:
-    Out << "MemberPointer: <todo>";
+    // FIXME: This is not enough to unambiguously identify the member in a
+    // multiple-inheritance scenario.
+    if (const ValueDecl *VD = getMemberPointerDecl()) {
+      Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
+      return;
+    }
+    Out << "0";
     return;
   }
   llvm_unreachable("Unknown APValue kind!");
 }
 
-const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
-                                           const APValue &V) {
-  llvm::SmallString<64> Buffer;
-  llvm::raw_svector_ostream Out(Buffer);
-  WriteShortAPValueToStream(Out, V);
-  return DB << Out.str();
+std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
+  std::string Result;
+  llvm::raw_string_ostream Out(Result);
+  printPretty(Out, Ctx, Ty);
+  return Result;
 }
 
 const APValue::LValueBase APValue::getLValueBase() const {