[clang] Rework how and when APValues are dumped
authorBruno Ricci <riccibrun@gmail.com>
Mon, 6 Jul 2020 20:50:23 +0000 (21:50 +0100)
committerBruno Ricci <riccibrun@gmail.com>
Mon, 6 Jul 2020 21:03:08 +0000 (22:03 +0100)
Currently APValues are dumped as a single string. This becomes quickly
completely unreadable since APValue is a tree-like structure. Even a simple
example is not pretty:

  struct S { int arr[4]; float f; };
  constexpr S s = { .arr = {1,2}, .f = 3.1415f };
  // Struct  fields: Array: Int: 1, Int: 2, 2 x Int: 0, Float: 3.141500e+00

With this patch this becomes:

  -Struct
   |-field: Array size=4
   | |-elements: Int 1, Int 2
   | `-filler: 2 x Int 0
   `-field: Float 3.141500e+00

Additionally APValues are currently only dumped as part of visiting a
ConstantExpr. This patch also dump the value of the initializer of constexpr
variable declarations:

  constexpr int foo(int a, int b) { return a + b - 42; }
  constexpr int a = 1, b = 2;
  constexpr int c = foo(a, b) > 0 ? foo(a, b) : foo(b, a);
  // VarDecl 0x62100008aec8 <col:3, col:57> col:17 c 'const int' constexpr cinit
  // |-value: Int -39
  // `-ConditionalOperator 0x62100008b4d0 <col:21, col:57> 'int'
  // <snip>

Do the above by moving the dump functions to TextNodeDumper which already has
the machinery to display trees. The cases APValue::LValue, APValue::MemberPointer
and APValue::AddrLabelDiff are left as they were before (unimplemented).

We try to display multiple elements on the same line if they are considered to
be "simple". This is to avoid wasting large amounts of vertical space in an
example like:

  constexpr int arr[8] = {0,1,2,3,4,5,6,7};
  // VarDecl 0x62100008bb78 <col:3, col:42> col:17 arr 'int const[8]' constexpr cinit
  // |-value: Array size=8
  // | |-elements: Int 0, Int 1, Int 2, Int 3
  // | `-elements: Int 4, Int 5, Int 6, Int 7

Differential Revision: https://reviews.llvm.org/D83183

Reviewed By: aaron.ballman

25 files changed:
clang/include/clang/AST/APValue.h
clang/include/clang/AST/ASTNodeTraverser.h
clang/include/clang/AST/JSONNodeDumper.h
clang/include/clang/AST/TextNodeDumper.h
clang/lib/AST/APValue.cpp
clang/lib/AST/ASTDumper.cpp
clang/lib/AST/JSONNodeDumper.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/test/AST/alignas_maybe_odr_cleanup.cpp
clang/test/AST/ast-dump-APValue-anon-union.cpp [new file with mode: 0644]
clang/test/AST/ast-dump-APValue-arithmetic.cpp [new file with mode: 0644]
clang/test/AST/ast-dump-APValue-array.cpp [new file with mode: 0644]
clang/test/AST/ast-dump-APValue-struct.cpp [new file with mode: 0644]
clang/test/AST/ast-dump-APValue-todo.cpp [new file with mode: 0644]
clang/test/AST/ast-dump-APValue-union.cpp [new file with mode: 0644]
clang/test/AST/ast-dump-APValue-vector.cpp [new file with mode: 0644]
clang/test/AST/ast-dump-attr.cpp
clang/test/AST/ast-dump-color.cpp
clang/test/AST/ast-dump-constant-expr.cpp
clang/test/AST/ast-dump-decl.cpp
clang/test/AST/ast-dump-records.cpp
clang/test/AST/ast-dump-stmt.cpp
clang/test/AST/pr43983.cpp
clang/test/Import/switch-stmt/test.cpp
clang/test/Tooling/clang-check-ast-dump.cpp

index c69974c..cca92b5 100644 (file)
@@ -372,7 +372,7 @@ public:
   bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
 
   void dump() const;
-  void dump(raw_ostream &OS, const ASTContext *Context) const;
+  void dump(raw_ostream &OS, const ASTContext &Context) const;
 
   void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
   std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
index f1c9819..26656b7 100644 (file)
 #include "clang/AST/LocInfoType.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/TemplateArgumentVisitor.h"
+#include "clang/AST/Type.h"
 #include "clang/AST/TypeVisitor.h"
 
 namespace clang {
 
+class APValue;
+
 /**
 
 ASTNodeTraverser traverses the Clang AST for dumping purposes.
@@ -50,6 +53,7 @@ struct {
   void Visit(const OMPClause *C);
   void Visit(const BlockDecl::Capture &C);
   void Visit(const GenericSelectionExpr::ConstAssociation &A);
+  void Visit(const APValue &Value, QualType Ty);
 };
 */
 template <typename Derived, typename NodeDelegateType>
@@ -211,6 +215,10 @@ public:
     });
   }
 
+  void Visit(const APValue &Value, QualType Ty) {
+    getNodeDelegate().AddChild([=] { getNodeDelegate().Visit(Value, Ty); });
+  }
+
   void Visit(const comments::Comment *C, const comments::FullComment *FC) {
     getNodeDelegate().AddChild([=] {
       getNodeDelegate().Visit(C, FC);
index ae7b4c9..4e71629 100644 (file)
 #include "clang/AST/CommentVisitor.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/Mangle.h"
+#include "clang/AST/Type.h"
 #include "llvm/Support/JSON.h"
 
 namespace clang {
 
+class APValue;
+
 class NodeStreamer {
   bool FirstChild = true;
   bool TopLevel = true;
@@ -201,6 +204,7 @@ public:
   void Visit(const OMPClause *C);
   void Visit(const BlockDecl::Capture &C);
   void Visit(const GenericSelectionExpr::ConstAssociation &A);
+  void Visit(const APValue &Value, QualType Ty);
 
   void VisitTypedefType(const TypedefType *TT);
   void VisitFunctionType(const FunctionType *T);
index d2ec153..b4cfb5a 100644 (file)
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/TemplateArgumentVisitor.h"
+#include "clang/AST/Type.h"
 #include "clang/AST/TypeVisitor.h"
 
 namespace clang {
 
+class APValue;
+
 class TextTreeStructure {
   raw_ostream &OS;
   const bool ShowColors;
@@ -153,6 +156,12 @@ class TextNodeDumper
 
   const char *getCommandName(unsigned CommandID);
 
+  void dumpAPValueChildren(const APValue &Value, QualType Ty,
+                           const APValue &(*IdxToChildFun)(const APValue &,
+                                                           unsigned),
+                           unsigned NumChildren, StringRef LabelSingular,
+                           StringRef LabelPlurial);
+
 public:
   TextNodeDumper(raw_ostream &OS, const ASTContext &Context, bool ShowColors);
   TextNodeDumper(raw_ostream &OS, bool ShowColors);
@@ -180,6 +189,8 @@ public:
 
   void Visit(const GenericSelectionExpr::ConstAssociation &A);
 
+  void Visit(const APValue &Value, QualType Ty);
+
   void dumpPointer(const void *Ptr);
   void dumpLocation(SourceLocation Loc);
   void dumpSourceRange(SourceRange R);
index 4179162..f3828bb 100644 (file)
@@ -386,92 +386,6 @@ static double GetApproxValue(const llvm::APFloat &F) {
   return V.convertToDouble();
 }
 
-LLVM_DUMP_METHOD void APValue::dump() const {
-  dump(llvm::errs(), /*Context=*/nullptr);
-  llvm::errs() << '\n';
-}
-
-LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
-                                    const ASTContext *Context) const {
-  switch (getKind()) {
-  case None:
-    OS << "None";
-    return;
-  case Indeterminate:
-    OS << "Indeterminate";
-    return;
-  case Int:
-    OS << "Int: " << getInt();
-    return;
-  case Float:
-    OS << "Float: " << GetApproxValue(getFloat());
-    return;
-  case FixedPoint:
-    OS << "FixedPoint : " << getFixedPoint();
-    return;
-  case Vector:
-    OS << "Vector: ";
-    getVectorElt(0).dump(OS, Context);
-    for (unsigned i = 1; i != getVectorLength(); ++i) {
-      OS << ", ";
-      getVectorElt(i).dump(OS, Context);
-    }
-    return;
-  case ComplexInt:
-    OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
-    return;
-  case ComplexFloat:
-    OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
-       << ", " << GetApproxValue(getComplexFloatImag());
-    return;
-  case LValue:
-    OS << "LValue: <todo>";
-    return;
-  case Array:
-    OS << "Array: ";
-    for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
-      getArrayInitializedElt(I).dump(OS, Context);
-      if (I != getArraySize() - 1)
-        OS << ", ";
-    }
-    if (hasArrayFiller()) {
-      OS << getArraySize() - getArrayInitializedElts() << " x ";
-      getArrayFiller().dump(OS, Context);
-    }
-    return;
-  case Struct:
-    OS << "Struct ";
-    if (unsigned N = getStructNumBases()) {
-      OS << " bases: ";
-      getStructBase(0).dump(OS, Context);
-      for (unsigned I = 1; I != N; ++I) {
-        OS << ", ";
-        getStructBase(I).dump(OS, Context);
-      }
-    }
-    if (unsigned N = getStructNumFields()) {
-      OS << " fields: ";
-      getStructField(0).dump(OS, Context);
-      for (unsigned I = 1; I != N; ++I) {
-        OS << ", ";
-        getStructField(I).dump(OS, Context);
-      }
-    }
-    return;
-  case Union:
-    OS << "Union: ";
-    getUnionValue().dump(OS, Context);
-    return;
-  case MemberPointer:
-    OS << "MemberPointer: <todo>";
-    return;
-  case AddrLabelDiff:
-    OS << "AddrLabelDiff: <todo>";
-    return;
-  }
-  llvm_unreachable("Unknown APValue kind!");
-}
-
 void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx,
                           QualType Ty) const {
   switch (getKind()) {
index 08a6d0c..284e5bd 100644 (file)
@@ -270,3 +270,19 @@ LLVM_DUMP_METHOD void Comment::dumpColor() const {
   ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
   Dumper.Visit(FC, FC);
 }
+
+//===----------------------------------------------------------------------===//
+// APValue method implementations
+//===----------------------------------------------------------------------===//
+
+LLVM_DUMP_METHOD void APValue::dump() const {
+  ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
+  Dumper.Visit(*this, /*Ty=*/QualType());
+}
+
+LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
+                                    const ASTContext &Context) const {
+  ASTDumper Dumper(llvm::errs(), Context,
+                   Context.getDiagnostics().getShowColors());
+  Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
+}
index c9a84a2..4bd00ec 100644 (file)
@@ -183,6 +183,13 @@ void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
   attributeOnlyIfTrue("selected", A.isSelected());
 }
 
+void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) {
+  std::string Str;
+  llvm::raw_string_ostream OS(Str);
+  Value.printPretty(OS, Ctx, Ty);
+  JOS.attribute("value", OS.str());
+}
+
 void JSONNodeDumper::writeIncludeStack(PresumedLoc Loc, bool JustFirst) {
   if (Loc.isInvalid())
     return;
@@ -1272,12 +1279,8 @@ void JSONNodeDumper::VisitCXXTypeidExpr(const CXXTypeidExpr *CTE) {
 }
 
 void JSONNodeDumper::VisitConstantExpr(const ConstantExpr *CE) {
-  if (CE->getResultAPValueKind() != APValue::None) {
-    std::string Str;
-    llvm::raw_string_ostream OS(Str);
-    CE->getAPValueResult().printPretty(OS, Ctx, CE->getType());
-    JOS.attribute("value", OS.str());
-  }
+  if (CE->getResultAPValueKind() != APValue::None)
+    Visit(CE->getAPValueResult(), CE->getType());
 }
 
 void JSONNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
index 74966f8..5b0a0ac 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/TextNodeDumper.h"
+#include "clang/AST/APValue.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclOpenMP.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/LocInfoType.h"
+#include "clang/AST/Type.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TypeTraits.h"
 
+#include <algorithm>
+#include <utility>
+
 using namespace clang;
 
 static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
@@ -350,6 +355,218 @@ void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
     OS << " selected";
 }
 
+static double GetApproxValue(const llvm::APFloat &F) {
+  llvm::APFloat V = F;
+  bool ignored;
+  V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
+            &ignored);
+  return V.convertToDouble();
+}
+
+/// True if the \p APValue \p Value can be folded onto the current line.
+static bool isSimpleAPValue(const APValue &Value) {
+  switch (Value.getKind()) {
+  case APValue::None:
+  case APValue::Indeterminate:
+  case APValue::Int:
+  case APValue::Float:
+  case APValue::FixedPoint:
+  case APValue::ComplexInt:
+  case APValue::ComplexFloat:
+  case APValue::LValue:
+  case APValue::MemberPointer:
+  case APValue::AddrLabelDiff:
+    return true;
+  case APValue::Vector:
+  case APValue::Array:
+  case APValue::Struct:
+    return false;
+  case APValue::Union:
+    return isSimpleAPValue(Value.getUnionValue());
+  }
+  llvm_unreachable("unexpected APValue kind!");
+}
+
+/// Dump the children of the \p APValue \p Value.
+///
+/// \param[in] Value          The \p APValue to visit
+/// \param[in] Ty             The \p QualType passed to \p Visit
+///
+/// \param[in] IdxToChildFun  A function mapping an \p APValue and an index
+///                           to one of the child of the \p APValue
+///
+/// \param[in] NumChildren    \p IdxToChildFun will be called on \p Value with
+///                           the indices in the range \p [0,NumChildren(
+///
+/// \param[in] LabelSingular  The label to use on a line with a single child
+/// \param[in] LabelPlurial   The label to use on a line with multiple children
+void TextNodeDumper::dumpAPValueChildren(
+    const APValue &Value, QualType Ty,
+    const APValue &(*IdxToChildFun)(const APValue &, unsigned),
+    unsigned NumChildren, StringRef LabelSingular, StringRef LabelPlurial) {
+  // To save some vertical space we print up to MaxChildrenPerLine APValues
+  // considered to be simple (by isSimpleAPValue) on a single line.
+  constexpr unsigned MaxChildrenPerLine = 4;
+  unsigned I = 0;
+  while (I < NumChildren) {
+    unsigned J = I;
+    while (J < NumChildren) {
+      if (isSimpleAPValue(IdxToChildFun(Value, J)) &&
+          (J - I < MaxChildrenPerLine)) {
+        ++J;
+        continue;
+      }
+      break;
+    }
+
+    J = std::max(I + 1, J);
+
+    // Print [I,J) on a single line.
+    AddChild(J - I > 1 ? LabelPlurial : LabelSingular, [=]() {
+      for (unsigned X = I; X < J; ++X) {
+        Visit(IdxToChildFun(Value, X), Ty);
+        if (X + 1 != J)
+          OS << ", ";
+      }
+    });
+    I = J;
+  }
+}
+
+void TextNodeDumper::Visit(const APValue &Value, QualType Ty) {
+  ColorScope Color(OS, ShowColors, ValueKindColor);
+  switch (Value.getKind()) {
+  case APValue::None:
+    OS << "None";
+    return;
+  case APValue::Indeterminate:
+    OS << "Indeterminate";
+    return;
+  case APValue::Int:
+    OS << "Int ";
+    {
+      ColorScope Color(OS, ShowColors, ValueColor);
+      OS << Value.getInt();
+    }
+    return;
+  case APValue::Float:
+    OS << "Float ";
+    {
+      ColorScope Color(OS, ShowColors, ValueColor);
+      OS << GetApproxValue(Value.getFloat());
+    }
+    return;
+  case APValue::FixedPoint:
+    OS << "FixedPoint ";
+    {
+      ColorScope Color(OS, ShowColors, ValueColor);
+      OS << Value.getFixedPoint();
+    }
+    return;
+  case APValue::Vector: {
+    unsigned VectorLength = Value.getVectorLength();
+    OS << "Vector length=" << VectorLength;
+
+    dumpAPValueChildren(
+        Value, Ty,
+        [](const APValue &Value, unsigned Index) -> const APValue & {
+          return Value.getVectorElt(Index);
+        },
+        VectorLength, "element", "elements");
+    return;
+  }
+  case APValue::ComplexInt:
+    OS << "ComplexInt ";
+    {
+      ColorScope Color(OS, ShowColors, ValueColor);
+      OS << Value.getComplexIntReal() << " + " << Value.getComplexIntImag()
+         << 'i';
+    }
+    return;
+  case APValue::ComplexFloat:
+    OS << "ComplexFloat ";
+    {
+      ColorScope Color(OS, ShowColors, ValueColor);
+      OS << GetApproxValue(Value.getComplexFloatReal()) << " + "
+         << GetApproxValue(Value.getComplexFloatImag()) << 'i';
+    }
+    return;
+  case APValue::LValue:
+    (void)Context;
+    OS << "LValue <todo>";
+    return;
+  case APValue::Array: {
+    unsigned ArraySize = Value.getArraySize();
+    unsigned NumInitializedElements = Value.getArrayInitializedElts();
+    OS << "Array size=" << ArraySize;
+
+    dumpAPValueChildren(
+        Value, Ty,
+        [](const APValue &Value, unsigned Index) -> const APValue & {
+          return Value.getArrayInitializedElt(Index);
+        },
+        NumInitializedElements, "element", "elements");
+
+    if (Value.hasArrayFiller()) {
+      AddChild("filler", [=] {
+        {
+          ColorScope Color(OS, ShowColors, ValueColor);
+          OS << ArraySize - NumInitializedElements << " x ";
+        }
+        Visit(Value.getArrayFiller(), Ty);
+      });
+    }
+
+    return;
+  }
+  case APValue::Struct: {
+    OS << "Struct";
+
+    dumpAPValueChildren(
+        Value, Ty,
+        [](const APValue &Value, unsigned Index) -> const APValue & {
+          return Value.getStructBase(Index);
+        },
+        Value.getStructNumBases(), "base", "bases");
+
+    dumpAPValueChildren(
+        Value, Ty,
+        [](const APValue &Value, unsigned Index) -> const APValue & {
+          return Value.getStructField(Index);
+        },
+        Value.getStructNumFields(), "field", "fields");
+
+    return;
+  }
+  case APValue::Union: {
+    OS << "Union";
+    {
+      ColorScope Color(OS, ShowColors, ValueColor);
+      if (const FieldDecl *FD = Value.getUnionField())
+        OS << " ." << *cast<NamedDecl>(FD);
+    }
+    // If the union value is considered to be simple, fold it into the
+    // current line to save some vertical space.
+    const APValue &UnionValue = Value.getUnionValue();
+    if (isSimpleAPValue(UnionValue)) {
+      OS << ' ';
+      Visit(UnionValue, Ty);
+    } else {
+      AddChild([=] { Visit(UnionValue, Ty); });
+    }
+
+    return;
+  }
+  case APValue::MemberPointer:
+    OS << "MemberPointer <todo>";
+    return;
+  case APValue::AddrLabelDiff:
+    OS << "AddrLabelDiff <todo>";
+    return;
+  }
+  llvm_unreachable("Unknown APValue kind!");
+}
+
 void TextNodeDumper::dumpPointer(const void *Ptr) {
   ColorScope Color(OS, ShowColors, AddressColor);
   OS << ' ' << Ptr;
@@ -712,11 +929,9 @@ void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) {
 }
 
 void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) {
-  if (Node->getResultAPValueKind() != APValue::None) {
-    ColorScope Color(OS, ShowColors, ValueColor);
-    OS << " ";
-    Node->getAPValueResult().dump(OS, Context);
-  }
+  if (Node->hasAPValueResult())
+    AddChild("value",
+             [=] { Visit(Node->getAPValueResult(), Node->getType()); });
 }
 
 void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
@@ -1454,6 +1669,16 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
     OS << " destroyed";
   if (D->isParameterPack())
     OS << " pack";
+
+  if (D->hasInit()) {
+    const Expr *E = D->getInit();
+    // Only dump the value of constexpr VarDecls for now.
+    if (E && !E->isValueDependent() && D->isConstexpr()) {
+      const APValue *Value = D->evaluateValue();
+      if (Value)
+        AddChild("value", [=] { Visit(*Value, E->getType()); });
+    }
+  }
 }
 
 void TextNodeDumper::VisitBindingDecl(const BindingDecl *D) {
index cdff1bf..3adef4c 100644 (file)
@@ -15,8 +15,9 @@ struct FOO {
   }
 };
 
-// CHECK: AlignedAttr {{.*}} alignas
-// CHECK: ConstantExpr {{.+}} 'int' Int: 32
-// CHECK: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
-// CHECK: DeclRefExpr {{.*}} 'const int' lvalue Var {{.*}} 'vec_align_bytes' 'const int' non_odr_use_constant
-// CHECK: NullStmt
+// CHECK:      |   `-AlignedAttr {{.*}} <col:14> alignas
+// CHECK-NEXT:      |     `-ConstantExpr {{.*}} <col:22> 'int'
+// CHECK-NEXT:      |       |-value: Int 32
+// CHECK-NEXT:      |       `-ImplicitCastExpr {{.*}} <col:22> 'int' <LValueToRValue>
+// CHECK-NEXT:      |         `-DeclRefExpr {{.*}} <col:22> 'const int' lvalue Var {{.*}} 'vec_align_bytes' 'const int' non_odr_use_constant
+// CHECK-NEXT:      `-NullStmt {{.*}} <line:14:5>
diff --git a/clang/test/AST/ast-dump-APValue-anon-union.cpp b/clang/test/AST/ast-dump-APValue-anon-union.cpp
new file mode 100644 (file)
index 0000000..c50fe70
--- /dev/null
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \
+// RUN:            -ast-dump %s -ast-dump-filter Test \
+// RUN: | FileCheck --strict-whitespace --match-full-lines %s
+
+struct S0 {
+  union {
+    int i = 42;
+  };
+};
+
+union U0 {
+  union {
+    float f = 3.1415f;
+  };
+};
+
+union U1 {
+  union {
+    float f;
+  };
+};
+
+void Test() {
+  constexpr S0 s0{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s0 'const S0' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Struct
+  // CHECK-NEXT:  |   | `-field: Union .i Int 42
+
+  constexpr U0 u0a{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0a 'const U0' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Union None
+
+  constexpr U0 u0b{3.1415f};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0b 'const U0' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Union . Union .f Float 3.141500e+00
+
+  constexpr U1 u1a{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1a 'const U1' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Union . Union .f Float 0.000000e+00
+
+  constexpr U1 u1b{3.1415f};
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1b 'const U1' constexpr listinit
+  // CHECK-NEXT:      |-value: Union . Union .f Float 3.141500e+00
+}
diff --git a/clang/test/AST/ast-dump-APValue-arithmetic.cpp b/clang/test/AST/ast-dump-APValue-arithmetic.cpp
new file mode 100644 (file)
index 0000000..a4e1d82
--- /dev/null
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \
+// RUN:            -ast-dump %s -ast-dump-filter Test \
+// RUN: | FileCheck --strict-whitespace --match-full-lines %s
+
+void Test() {
+  constexpr int Int = 42;
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} Int 'const int' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Int 42
+
+  constexpr __int128 Int128 = (__int128)0xFFFFFFFFFFFFFFFF + (__int128)1;
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} Int128 'const __int128' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Int 18446744073709551616
+
+  constexpr float Float = 3.1415f;
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} Float 'const float' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Float 3.141500e+00
+
+  constexpr double Double = 3.1415f;
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} Double 'const double' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Float 3.141500e+00
+
+  constexpr _Complex int ComplexInt = 42 + 24i;
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} referenced ComplexInt 'const _Complex int' constexpr cinit
+  // CHECK-NEXT:  |   |-value: ComplexInt 42 + 24i
+
+  constexpr _Complex float ComplexFloat = 3.1415f + 42i;
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} referenced ComplexFloat 'const _Complex float' constexpr cinit
+  // CHECK-NEXT:  |   |-value: ComplexFloat 3.141500e+00 + 4.200000e+01i
+
+  constexpr _Complex int ArrayOfComplexInt[10] = {ComplexInt, ComplexInt, ComplexInt, ComplexInt};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} ArrayOfComplexInt '_Complex int const[10]' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Array size=10
+  // CHECK-NEXT:  |   | |-elements: ComplexInt 42 + 24i, ComplexInt 42 + 24i, ComplexInt 42 + 24i, ComplexInt 42 + 24i
+  // CHECK-NEXT:  |   | `-filler: 6 x ComplexInt 0 + 0i
+
+  constexpr _Complex float ArrayOfComplexFloat[10] = {ComplexFloat, ComplexFloat, ComplexInt, ComplexInt};
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} ArrayOfComplexFloat '_Complex float const[10]' constexpr cinit
+  // CHECK-NEXT:      |-value: Array size=10
+  // CHECK-NEXT:      | |-elements: ComplexFloat 3.141500e+00 + 4.200000e+01i, ComplexFloat 3.141500e+00 + 4.200000e+01i, ComplexFloat 4.200000e+01 + 2.400000e+01i, ComplexFloat 4.200000e+01 + 2.400000e+01i
+  // CHECK-NEXT:      | `-filler: 6 x ComplexFloat 0.000000e+00 + 0.000000e+00i
+}
diff --git a/clang/test/AST/ast-dump-APValue-array.cpp b/clang/test/AST/ast-dump-APValue-array.cpp
new file mode 100644 (file)
index 0000000..4b7dfab
--- /dev/null
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \
+// RUN:            -ast-dump %s -ast-dump-filter Test \
+// RUN: | FileCheck --strict-whitespace --match-full-lines %s
+
+struct S0 {
+  int arr[2];
+};
+union U0 {
+  int i;
+  float f;
+};
+
+struct S1 {
+  S0 s0 = {1, 2};
+  U0 u0 = {.i = 42};
+};
+
+void Test() {
+  constexpr int __attribute__((vector_size(sizeof(int) * 5))) arr_v5i[5] = {
+      {1, 2, 3, 4, 5},
+      {1, 2, 3, 4},
+  };
+  // CHECK:  | `-VarDecl {{.*}} <line:{{.*}}, line:{{.*}}> line:{{.*}} arr_v5i '__attribute__((__vector_size__(5 * sizeof(int)))) int const[5]' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Array size=5
+  // CHECK-NEXT:  |   | |-element: Vector length=5
+  // CHECK-NEXT:  |   | | |-elements: Int 1, Int 2, Int 3, Int 4
+  // CHECK-NEXT:  |   | | `-element: Int 5
+  // CHECK-NEXT:  |   | |-element: Vector length=5
+  // CHECK-NEXT:  |   | | |-elements: Int 1, Int 2, Int 3, Int 4
+  // CHECK-NEXT:  |   | | `-element: Int 0
+  // CHECK-NEXT:  |   | `-filler: 3 x Vector length=5
+  // CHECK-NEXT:  |   |   |-elements: Int 0, Int 0, Int 0, Int 0
+  // CHECK-NEXT:  |   |   `-element: Int 0
+
+  constexpr float arr_f[3][5] = {
+      {1, 2, 3, 4, 5},
+  };
+  // CHECK:  | `-VarDecl {{.*}} <line:{{.*}}, line:{{.*}}> line:{{.*}} arr_f 'float const[3][5]' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Array size=3
+  // CHECK-NEXT:  |   | |-element: Array size=5
+  // CHECK-NEXT:  |   | | |-elements: Float 1.000000e+00, Float 2.000000e+00, Float 3.000000e+00, Float 4.000000e+00
+  // CHECK-NEXT:  |   | | `-element: Float 5.000000e+00
+  // CHECK-NEXT:  |   | `-filler: 2 x Array size=5
+  // CHECK-NEXT:  |   |   `-filler: 5 x Float 0.000000e+00
+
+  constexpr S0 arr_s0[2] = {{1, 2}, {3, 4}};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} arr_s0 'S0 const[2]' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Array size=2
+  // CHECK-NEXT:  |   | |-element: Struct
+  // CHECK-NEXT:  |   | | `-field: Array size=2
+  // CHECK-NEXT:  |   | |   `-elements: Int 1, Int 2
+  // CHECK-NEXT:  |   | `-element: Struct
+  // CHECK-NEXT:  |   |   `-field: Array size=2
+  // CHECK-NEXT:  |   |     `-elements: Int 3, Int 4
+
+  constexpr U0 arr_u0[2] = {{.i = 42}, {.f = 3.1415f}};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} arr_u0 'U0 const[2]' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Array size=2
+  // CHECK-NEXT:  |   | `-elements: Union .i Int 42, Union .f Float 3.141500e+00
+
+  constexpr S1 arr_s1[2] = {};
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} arr_s1 'S1 const[2]' constexpr cinit
+  // CHECK-NEXT:      |-value: Array size=2
+  // CHECK-NEXT:      | |-element: Struct
+  // CHECK-NEXT:      | | |-field: Struct
+  // CHECK-NEXT:      | | | `-field: Array size=2
+  // CHECK-NEXT:      | | |   `-elements: Int 1, Int 2
+  // CHECK-NEXT:      | | `-field: Union .i Int 42
+  // CHECK-NEXT:      | `-element: Struct
+  // CHECK-NEXT:      |   |-field: Struct
+  // CHECK-NEXT:      |   | `-field: Array size=2
+  // CHECK-NEXT:      |   |   `-elements: Int 1, Int 2
+  // CHECK-NEXT:      |   `-field: Union .i Int 42
+}
diff --git a/clang/test/AST/ast-dump-APValue-struct.cpp b/clang/test/AST/ast-dump-APValue-struct.cpp
new file mode 100644 (file)
index 0000000..d69ddff
--- /dev/null
@@ -0,0 +1,105 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \
+// RUN:            -ast-dump %s -ast-dump-filter Test \
+// RUN: | FileCheck --strict-whitespace --match-full-lines %s
+
+struct S0 {
+  int i = 0;
+  union {
+    int j = 0;
+  } u0;
+};
+
+struct S1 {
+  int i = 0;
+  union {
+    struct {
+      int j = 0;
+    } s;
+  } u1;
+};
+
+struct S2 {
+  int i = 0;
+  union {
+    union {
+      int j = 0;
+    } u;
+  } u2;
+};
+
+struct S3 {
+  int i = 0;
+  union {
+    union {
+      struct {
+        int j = 0;
+      } j;
+    } u;
+  } u3;
+};
+
+struct S4 : S0 {
+  int i = 1, j = 2, k = 3;
+  struct {
+  } s;
+  int a = 4, b = 5, c = 6;
+};
+
+struct S5 : S4 {
+  int arr0[8] = {1, 2, 3, 4};
+  int arr1[8] = {1, 2, 3, 4, 0, 0, 0, 0};
+};
+
+void Test() {
+  constexpr S0 s0{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s0 'const S0' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Struct
+  // CHECK-NEXT:  |   | `-fields: Int 0, Union .j Int 0
+
+  constexpr S1 s1{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s1 'const S1' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Struct
+  // CHECK-NEXT:  |   | |-field: Int 0
+  // CHECK-NEXT:  |   | `-field: Union .s
+  // CHECK-NEXT:  |   |   `-Struct
+  // CHECK-NEXT:  |   |     `-field: Int 0
+
+  constexpr S2 s2{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s2 'const S2' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Struct
+  // CHECK-NEXT:  |   | `-fields: Int 0, Union .u Union .j Int 0
+
+  constexpr S3 s3{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s3 'const S3' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Struct
+  // CHECK-NEXT:  |   | |-field: Int 0
+  // CHECK-NEXT:  |   | `-field: Union .u
+  // CHECK-NEXT:  |   |   `-Union .j
+  // CHECK-NEXT:  |   |     `-Struct
+  // CHECK-NEXT:  |   |       `-field: Int 0
+
+  constexpr S4 s4{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s4 'const S4' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Struct
+  // CHECK-NEXT:  |   | |-base: Struct
+  // CHECK-NEXT:  |   | | `-fields: Int 0, Union .j Int 0
+  // CHECK-NEXT:  |   | |-fields: Int 1, Int 2, Int 3
+  // CHECK-NEXT:  |   | |-field: Struct
+  // CHECK-NEXT:  |   | `-fields: Int 4, Int 5, Int 6
+
+  constexpr S5 s5{};
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} s5 'const S5' constexpr listinit
+  // CHECK-NEXT:      |-value: Struct
+  // CHECK-NEXT:      | |-base: Struct
+  // CHECK-NEXT:      | | |-base: Struct
+  // CHECK-NEXT:      | | | `-fields: Int 0, Union .j Int 0
+  // CHECK-NEXT:      | | |-fields: Int 1, Int 2, Int 3
+  // CHECK-NEXT:      | | |-field: Struct
+  // CHECK-NEXT:      | | `-fields: Int 4, Int 5, Int 6
+  // CHECK-NEXT:      | |-field: Array size=8
+  // CHECK-NEXT:      | | |-elements: Int 1, Int 2, Int 3, Int 4
+  // CHECK-NEXT:      | | `-filler: 4 x Int 0
+  // CHECK-NEXT:      | `-field: Array size=8
+  // CHECK-NEXT:      |   |-elements: Int 1, Int 2, Int 3, Int 4
+  // CHECK-NEXT:      |   `-elements: Int 0, Int 0, Int 0, Int 0
+}
diff --git a/clang/test/AST/ast-dump-APValue-todo.cpp b/clang/test/AST/ast-dump-APValue-todo.cpp
new file mode 100644 (file)
index 0000000..5de8146
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \
+// RUN:            -ast-dump %s -ast-dump-filter Test \
+// RUN: | FileCheck --strict-whitespace --match-full-lines %s
+
+int i;
+struct S {
+  int i;
+};
+
+void Test() {
+  constexpr int *pi = &i;
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pi 'int *const' constexpr cinit
+  // CHECK-NEXT:  |   |-value: LValue <todo>
+
+  constexpr int(S::*pmi) = &S::i;
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pmi 'int (S::*const)' constexpr cinit
+  // CHECK-NEXT:      |-value: MemberPointer <todo>
+}
diff --git a/clang/test/AST/ast-dump-APValue-union.cpp b/clang/test/AST/ast-dump-APValue-union.cpp
new file mode 100644 (file)
index 0000000..afb69de
--- /dev/null
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \
+// RUN:            -ast-dump %s -ast-dump-filter Test \
+// RUN: | FileCheck --strict-whitespace --match-full-lines %s
+
+union U0 {
+  int i = 42;
+  float f;
+};
+
+union U1 {
+  union Uinner {
+    int i;
+    float f = 3.1415f;
+  } uinner;
+};
+
+union U2 {
+  union Uinner {
+    double d;
+    int arr[2] = {1, 2};
+  } uinner;
+};
+
+union U3 {
+  union Uinner {
+    double d = 3.1415;
+    int arr[2];
+  } uinner;
+  float f;
+};
+
+void Test() {
+  constexpr U0 u0{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0 'const U0' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Union .i Int 42
+
+  constexpr U1 u1{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1 'const U1' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Union .uinner Union .f Float 3.141500e+00
+
+  constexpr U2 u2{};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u2 'const U2' constexpr listinit
+  // CHECK-NEXT:  |   |-value: Union .uinner
+  // CHECK-NEXT:  |   | `-Union .arr
+  // CHECK-NEXT:  |   |   `-Array size=2
+  // CHECK-NEXT:  |   |     `-elements: Int 1, Int 2
+
+  constexpr U3 u3a = {.f = 3.1415};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u3a 'const U3' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Union .f Float 3.141500e+00
+
+  constexpr U3 u3b = {.uinner = {}};
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u3b 'const U3' constexpr cinit
+  // CHECK-NEXT:      |-value: Union .uinner Union .d Float 3.141500e+00
+}
diff --git a/clang/test/AST/ast-dump-APValue-vector.cpp b/clang/test/AST/ast-dump-APValue-vector.cpp
new file mode 100644 (file)
index 0000000..fe2dcd9
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -std=gnu++17 \
+// RUN:            -ast-dump %s -ast-dump-filter Test \
+// RUN: | FileCheck --strict-whitespace --match-full-lines %s
+
+void Test() {
+  constexpr int __attribute__((vector_size(sizeof(int) * 1))) v1i = {1};
+  // CHECK:  |-DeclStmt {{.*}} <line:{{.*}}, col:{{.*}}>
+  // CHECK-NEXT:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} v1i '__attribute__((__vector_size__(1 * sizeof(int)))) int const' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Vector length=1
+  // CHECK-NEXT:  |   | `-element: Int 1
+
+  constexpr int __attribute__((vector_size(sizeof(int) * 4))) v4i = {1, 2, 3, 4};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} v4i '__attribute__((__vector_size__(4 * sizeof(int)))) int const' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Vector length=4
+  // CHECK-NEXT:  |   | `-elements: Int 1, Int 2, Int 3, Int 4
+
+  constexpr int __attribute__((vector_size(sizeof(int) * 5))) v5i = {1, 2, 3, 4};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} v5i '__attribute__((__vector_size__(5 * sizeof(int)))) int const' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Vector length=5
+  // CHECK-NEXT:  |   | |-elements: Int 1, Int 2, Int 3, Int 4
+  // CHECK-NEXT:  |   | `-element: Int 0
+
+  constexpr int __attribute__((vector_size(sizeof(int) * 8))) v8i = {1, 2, 3, 4};
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} v8i '__attribute__((__vector_size__(8 * sizeof(int)))) int const' constexpr cinit
+  // CHECK-NEXT:  |   |-value: Vector length=8
+  // CHECK-NEXT:  |   | |-elements: Int 1, Int 2, Int 3, Int 4
+  // CHECK-NEXT:  |   | `-elements: Int 0, Int 0, Int 0, Int 0
+
+  constexpr int __attribute__((vector_size(sizeof(int) * 9))) v9i = {1, 2, 3, 4};
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} v9i '__attribute__((__vector_size__(9 * sizeof(int)))) int const' constexpr cinit
+  // CHECK-NEXT:      |-value: Vector length=9
+  // CHECK-NEXT:      | |-elements: Int 1, Int 2, Int 3, Int 4
+  // CHECK-NEXT:      | |-elements: Int 0, Int 0, Int 0, Int 0
+  // CHECK-NEXT:      | `-element: Int 0
+}
index 50eef3e..95491a0 100644 (file)
@@ -45,6 +45,7 @@ int TestAlignedExpr __attribute__((aligned(4)));
 // CHECK:      VarDecl{{.*}}TestAlignedExpr\r
 // CHECK-NEXT:   AlignedAttr {{.*}} aligned\r
 // CHECK-NEXT:     ConstantExpr\r
+// CHECK-NEXT:       value: Int 4\r
 // CHECK-NEXT:       IntegerLiteral\r
 \r
 int TestEnum __attribute__((visibility("default")));\r
index 6651ef2..baaf972 100644 (file)
@@ -49,13 +49,15 @@ struct Invalid {
 //CHECK: {{^}}[[Blue]]| |   |-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:10:11[[RESET]]> [[Green]]'int'[[RESET]][[Cyan:.\[0;36m]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |   `-[[RESET]][[MAGENTA]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:14[[RESET]], [[Yellow]]line:15:3[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:3[[RESET]], [[Yellow]]line:12:27[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| |     | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] Int: 1[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| |     | |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| |     | | |-value: [[RESET]][[Cyan]]Int [[CYAN]]1[[RESET]][[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |     | | `-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |     | `-[[RESET]][[MAGENTA]]AttributedStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:12:5[[RESET]], [[Yellow]]col:27[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |   |-[[RESET]][[BLUE]]FallThroughAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:7[[RESET]], [[Yellow]]col:14[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |   `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:27[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     `-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:3[[RESET]], [[Yellow]]line:14:5[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| |       |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] Int: 2[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| |       |-[[RESET]][[MAGENTA]]ConstantExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| |       | |-value: [[RESET]][[Cyan]]Int [[CYAN]]2[[RESET]][[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |       | `-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 2[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |       `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:14:5[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]FullComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:8:4[[RESET]], [[Yellow]]col:11[[RESET]]>{{$}}
index c9ddb24..43f68ca 100644 (file)
@@ -54,27 +54,32 @@ void Test() {
 // CHECK-NEXT:FunctionDecl {{.*}} <{{.*}}ast-dump-constant-expr.cpp:42:1, line:52:1> line:42:6{{( imported)?}} Test 'void ()'
 // CHECK-NEXT:`-CompoundStmt {{.*}} <col:13, line:52:1>
 // CHECK-NEXT:  |-CStyleCastExpr {{.*}} <line:43:3, col:19> 'void' <ToVoid>
-// CHECK-NEXT:  | `-ConstantExpr {{.*}} <col:10, col:19> 'int' Int: 42
+// CHECK-NEXT:  | `-ConstantExpr {{.*}} <col:10, col:19> 'int'
+// CHECK-NEXT:  |   |-value: Int 42
 // CHECK-NEXT:  |   `-CallExpr {{.*}} <col:10, col:19> 'int'
 // CHECK-NEXT:  |     `-ImplicitCastExpr {{.*}} <col:10> 'int (*)()' <FunctionToPointerDecay>
 // CHECK-NEXT:  |       `-DeclRefExpr {{.*}} <col:10> 'int ()' lvalue Function {{.*}} 'test_Int' 'int ()'
 // CHECK-NEXT:  |-CStyleCastExpr {{.*}} <line:44:3, col:21> 'void' <ToVoid>
-// CHECK-NEXT:  | `-ConstantExpr {{.*}} <col:10, col:21> 'float' Float: 1.000000e+00
+// CHECK-NEXT:  | `-ConstantExpr {{.*}} <col:10, col:21> 'float'
+// CHECK-NEXT:  |   |-value: Float 1.000000e+00
 // CHECK-NEXT:  |   `-CallExpr {{.*}} <col:10, col:21> 'float'
 // CHECK-NEXT:  |     `-ImplicitCastExpr {{.*}} <col:10> 'float (*)()' <FunctionToPointerDecay>
 // CHECK-NEXT:  |       `-DeclRefExpr {{.*}} <col:10> 'float ()' lvalue Function {{.*}} 'test_Float' 'float ()'
 // CHECK-NEXT:  |-CStyleCastExpr {{.*}} <line:45:3, col:26> 'void' <ToVoid>
-// CHECK-NEXT:  | `-ConstantExpr {{.*}} <col:10, col:26> '_Complex int' ComplexInt: 1, 2
+// CHECK-NEXT:  | `-ConstantExpr {{.*}} <col:10, col:26> '_Complex int'
+// CHECK-NEXT:  |   |-value: ComplexInt 1 + 2i
 // CHECK-NEXT:  |   `-CallExpr {{.*}} <col:10, col:26> '_Complex int'
 // CHECK-NEXT:  |     `-ImplicitCastExpr {{.*}} <col:10> '_Complex int (*)()' <FunctionToPointerDecay>
 // CHECK-NEXT:  |       `-DeclRefExpr {{.*}} <col:10> '_Complex int ()' lvalue Function {{.*}} 'test_ComplexInt' '_Complex int ()'
 // CHECK-NEXT:  |-CStyleCastExpr {{.*}} <line:46:3, col:28> 'void' <ToVoid>
-// CHECK-NEXT:  | `-ConstantExpr {{.*}} <col:10, col:28> '_Complex float' ComplexFloat: 1.200000e+00, 3.400000e+00
+// CHECK-NEXT:  | `-ConstantExpr {{.*}} <col:10, col:28> '_Complex float'
+// CHECK-NEXT:  |   |-value: ComplexFloat 1.200000e+00 + 3.400000e+00i
 // CHECK-NEXT:  |   `-CallExpr {{.*}} <col:10, col:28> '_Complex float'
 // CHECK-NEXT:  |     `-ImplicitCastExpr {{.*}} <col:10> '_Complex float (*)()' <FunctionToPointerDecay>
 // CHECK-NEXT:  |       `-DeclRefExpr {{.*}} <col:10> '_Complex float ()' lvalue Function {{.*}} 'test_ComplexFloat' '_Complex float ()'
 // CHECK-NEXT:  `-CStyleCastExpr {{.*}} <line:47:3, col:22> 'void' <ToVoid>
-// CHECK-NEXT:    `-ConstantExpr {{.*}} <col:10, col:22> '__int128' Int: 18446744073709551616
+// CHECK-NEXT:    `-ConstantExpr {{.*}} <col:10, col:22> '__int128'
+// CHECK-NEXT:      |-value: Int 18446744073709551616
 // CHECK-NEXT:      `-CallExpr {{.*}} <col:10, col:22> '__int128'
 // CHECK-NEXT:        `-ImplicitCastExpr {{.*}} <col:10> '__int128 (*)()' <FunctionToPointerDecay>
 // CHECK-NEXT:          `-DeclRefExpr {{.*}} <col:10> '__int128 ()' lvalue Function {{.*}} 'test_Int128' '__int128 ()'
index b9b7cba..97bb796 100644 (file)
@@ -439,6 +439,7 @@ namespace testClassTemplateDecl {
 // CHECK-NEXT:  |-NonTypeTemplateParmDecl 0x{{.+}} <col:12, col:20> col:16 'int' depth 0 index 0 I\r
 // CHECK-NEXT:  | `-TemplateArgument expr\r
 // CHECK-NEXT:  |   `-ConstantExpr 0x{{.+}} <col:20> 'int'\r
+// CHECK-NEXT:  |     |-value: Int 42\r
 // CHECK-NEXT:  |     `-IntegerLiteral 0x{{.+}} <col:20> 'int' 42\r
 // CHECK-NEXT:  `-CXXRecordDecl 0x{{.+}} <col:24, col:31> col:31 struct TestTemplateDefaultNonType\r
 \r
@@ -644,6 +645,7 @@ namespace TestNonTypeTemplateParmDecl {
 // CHECK-NEXT:     NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I\r
 // CHECK-NEXT:       TemplateArgument expr\r
 // CHECK-NEXT:         ConstantExpr{{.*}} 'int'\r
+// CHECK-NEXT:           value: Int 1\r
 // CHECK-NEXT:           IntegerLiteral{{.*}} 'int' 1\r
 // CHECK-NEXT:     NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J\r
 \r
index f379b2d..cb7ac83 100644 (file)
@@ -15,7 +15,7 @@ struct B;
 // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:8> col:8 referenced struct B
 
 struct A {
-  // CHECK: CXXRecordDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+29]]:1> line:[[@LINE-1]]:8 struct A definition
+  // CHECK: CXXRecordDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+32]]:1> line:[[@LINE-1]]:8 struct A definition
   // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
   // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
   // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
@@ -33,14 +33,17 @@ struct A {
   int d : 12;
   // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 d 'int'
   // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+  // CHECK-NEXT: value: Int 12
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 12
   int : 0;
   // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:7 'int'
   // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:9> 'int'
+  // CHECK-NEXT: value: Int 0
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:9> 'int' 0
   int e : 10;
   // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 e 'int'
   // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+  // CHECK-NEXT: value: Int 10
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 10
   B *f;
   // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:6> col:6 f 'B *'
@@ -141,7 +144,7 @@ union F;
 // CHECK: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:7> col:7 union F
 
 union E {
-  // CHECK: CXXRecordDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+29]]:1> line:[[@LINE-1]]:7 union E definition
+  // CHECK: CXXRecordDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+32]]:1> line:[[@LINE-1]]:7 union E definition
   // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal
   // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit
   // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
@@ -159,14 +162,17 @@ union E {
   int d : 12;
   // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 d 'int'
   // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+  // CHECK-NEXT: value: Int 12
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 12
   int : 0;
   // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:9> col:7 'int'
   // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:9> 'int'
+  // CHECK-NEXT: value: Int 0
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:9> 'int' 0
   int e : 10;
   // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:11> col:7 e 'int'
   // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <col:11> 'int'
+  // CHECK-NEXT: value: Int 10
   // CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:11> 'int' 10
   B *f;
   // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:6> col:6 f 'B *'
index e4d8d82..585a94b 100644 (file)
@@ -130,6 +130,7 @@ void TestIf(bool b) {
     ;
   // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-2]]:3, line:[[@LINE-1]]:5>
   // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <line:[[@LINE-3]]:17, col:30> 'bool'
+  // CHECK-NEXT: value: Int 1
   // CHECK-NEXT: BinaryOperator
   // CHECK-NEXT: UnaryExprOrTypeTraitExpr
   // CHECK-NEXT: ParenExpr
@@ -144,6 +145,7 @@ void TestIf(bool b) {
     ;
   // CHECK: IfStmt 0x{{[^ ]*}} <line:[[@LINE-4]]:3, line:[[@LINE-1]]:5> has_else
   // CHECK-NEXT: ConstantExpr 0x{{[^ ]*}} <line:[[@LINE-5]]:17, col:30> 'bool'
+  // CHECK-NEXT: value: Int 1
   // CHECK-NEXT: BinaryOperator
   // CHECK-NEXT: UnaryExprOrTypeTraitExpr
   // CHECK-NEXT: ParenExpr
index dd7ce76..c27d825 100644 (file)
@@ -9,6 +9,7 @@
 
 struct B { _Alignas(64) struct { int b; };   };
 
-// CHECK: AlignedAttr {{.*}} _Alignas
-// CHECK: ConstantExpr {{.*}} 64
-// CHECK: IntegerLiteral {{.*}} 64
+// CHECK:  | `-AlignedAttr {{.*}} <col:12> _Alignas
+// CHECK-NEXT:  |   `-ConstantExpr {{.*}} <col:21> 'int'
+// CHECK-NEXT:  |     |-value: Int 64
+// CHECK-NEXT:  |     `-IntegerLiteral {{.*}} <col:21> 'int' 64
index e274e89..fcd8263 100644 (file)
@@ -5,20 +5,26 @@
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 1
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 2
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: BreakStmt
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 3
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 4
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 5
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 5
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: BreakStmt
 
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 1
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: BreakStmt
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 2
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: BreakStmt
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 3
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: ConstantExpr
+// CHECK-NEXT: value: Int 5
 // CHECK-NEXT: IntegerLiteral
 // CHECK-NEXT: BreakStmt
 
index 496d489..bd9ae5f 100644 (file)
@@ -33,6 +33,7 @@
 // CHECK-ATTR-NEXT: FieldDecl{{.*}}n
 // CHECK-ATTR-NEXT:   AlignedAttr
 // CHECK-ATTR-NEXT:     ConstantExpr
+// CHECK-ATTR-NEXT:       value: Int 2
 // CHECK-ATTR-NEXT:       BinaryOperator
 //
 // RUN: clang-check -ast-dump -ast-dump-filter test_namespace::AfterNullNode "%s" -- 2>&1 | FileCheck -check-prefix CHECK-AFTER-NULL %s