Skip to content

Conversation

sei-nreimer
Copy link

AST output modifications primarily focused on JSON enhancements for the SEI Redemption project. Some of the key changes are:

  1. Recursive Pointer Resolution
  • Modified the AST to accurately track multiple levels of pointer indirection during analysis
  1. Function Pointer Identification
  • Improved function pointer type identification handling, enabling correct resolution and analysis of function pointer assignments and calls within the AST
  1. QualType Enhancements
  • Updated QualType to better represent types with qualifiers such as const, volatile, and others
  1. QualDetails Addition
  • Introduced a new structure, QualDetails, to encapsulate additional metadata about type qualifiers, e.g., ptr, signed, float, struct, union, array, promotable, integer, func_ptr
  1. Return Type Information
  • Updated the AST to expose detailed return type information, similar to VarDecl
  1. JSON Debloating:
  • Reduced the size of JSON output by caching IDs and then using the refID key for referring back to the original ID
  1. Added Missing Range and ID for CXXCtorInitializer

Examples

// recursive pointer resolution
int ** c;

image

// function pointer information
long (*foo)(int (*)(short));

image

// return type information
int runFunctionTestA( char a );

image

// refID usage example. 
int a; // (not in image) first time encountering an int
int *b; // (not in image) first time encountering int *, but second time encountering int
int **c;  // first time encountering int **, but second time encountering int * and third time int

image

Copy link

github-actions bot commented Aug 6, 2025

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V clang:frontend Language frontend issues, e.g. anything involving "Sema" HLSL HLSL Language Support clang:openmp OpenMP related changes to Clang clang:bytecode Issues for the clang bytecode constexpr interpreter labels Aug 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 6, 2025

@llvm/pr-subscribers-hlsl

@llvm/pr-subscribers-backend-risc-v

Author: Nicholas Reimer (sei-nreimer)

Changes

AST output modifications primarily focused on JSON enhancements for the SEI Redemption project. Some of the key changes are:

  1. Recursive Pointer Resolution
  • Modified the AST to accurately track multiple levels of pointer indirection during analysis
  1. Function Pointer Identification
  • Improved function pointer type identification handling, enabling correct resolution and analysis of function pointer assignments and calls within the AST
  1. QualType Enhancements
  • Updated QualType to better represent types with qualifiers such as const, volatile, and others
  1. QualDetails Addition
  • Introduced a new structure, QualDetails, to encapsulate additional metadata about type qualifiers, e.g., ptr, signed, float, struct, union, array, promotable, integer, func_ptr
  1. Return Type Information
  • Updated the AST to expose detailed return type information, similar to VarDecl
  1. JSON Debloating:
  • Reduced the size of JSON output by caching IDs and then using the refID key for referring back to the original ID
  1. Added Missing Range and ID for CXXCtorInitializer

Examples

// recursive pointer resolution
int ** c;

image

// function pointer information
long (*foo)(int (*)(short));

image

// return type information
int runFunctionTestA( char a );

image

// refID usage example. 
int a; // (not in image) first time encountering an int
int *b; // (not in image) first time encountering int *, but second time encountering int
int **c;  // first time encountering int **, but second time encountering int * and third time int

image


Patch is 9.88 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/152372.diff

174 Files Affected:

  • (modified) clang/include/clang/AST/ASTNodeTraverser.h (+59-4)
  • (modified) clang/include/clang/AST/JSONNodeDumper.h (+47-2)
  • (modified) clang/include/clang/AST/TextNodeDumper.h (+25)
  • (modified) clang/lib/AST/JSONNodeDumper.cpp (+124-4)
  • (modified) clang/lib/AST/TextNodeDumper.cpp (+15)
  • (modified) clang/test/AST/ByteCode/builtin-constant-p.cpp (-8)
  • (modified) clang/test/AST/ByteCode/complex.cpp (+1-1)
  • (modified) clang/test/AST/ByteCode/const-eval.c (-3)
  • (modified) clang/test/AST/ByteCode/cxx23.cpp (-19)
  • (modified) clang/test/AST/ByteCode/placement-new.cpp (-8)
  • (modified) clang/test/AST/ByteCode/records.cpp (+1-1)
  • (modified) clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl (+52-52)
  • (modified) clang/test/AST/HLSL/OutArgExpr.hlsl (+4-4)
  • (modified) clang/test/AST/HLSL/RootSignatures-AST.hlsl (+5-5)
  • (modified) clang/test/AST/HLSL/StructuredBuffers-AST.hlsl (+159-159)
  • (modified) clang/test/AST/HLSL/TypdefArrayParam.hlsl (+3-3)
  • (modified) clang/test/AST/HLSL/TypedBuffers-AST.hlsl (+112-112)
  • (modified) clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl (+161-8)
  • (modified) clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl (+10-12)
  • (modified) clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl (+6-6)
  • (modified) clang/test/AST/HLSL/packoffset.hlsl (+305-49)
  • (modified) clang/test/AST/HLSL/pch_hlsl_buffer.hlsl (+16-16)
  • (modified) clang/test/AST/HLSL/resource_binding_attr.hlsl (+192-24)
  • (modified) clang/test/AST/alignas_maybe_odr_cleanup.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-aarch64-sve-types.c (+15-15)
  • (modified) clang/test/AST/ast-dump-arm-attr.c (+1-1)
  • (modified) clang/test/AST/ast-dump-array.cpp (+60-4)
  • (modified) clang/test/AST/ast-dump-atomic-options.hip (+217-64)
  • (modified) clang/test/AST/ast-dump-attr-json.cpp (+654-531)
  • (modified) clang/test/AST/ast-dump-attr-type.cpp (+11-11)
  • (modified) clang/test/AST/ast-dump-attr.cpp (+331-298)
  • (modified) clang/test/AST/ast-dump-attr.m (+3-3)
  • (modified) clang/test/AST/ast-dump-c-attr.c (+13-11)
  • (modified) clang/test/AST/ast-dump-comment.cpp (+5-5)
  • (modified) clang/test/AST/ast-dump-concepts.cpp (+9-9)
  • (modified) clang/test/AST/ast-dump-constant-var.cu (+2-2)
  • (modified) clang/test/AST/ast-dump-coroutine.cpp (+343-67)
  • (modified) clang/test/AST/ast-dump-ctad-alias.cpp (+19-19)
  • (modified) clang/test/AST/ast-dump-decl-json.c (+1993-1650)
  • (modified) clang/test/AST/ast-dump-decl-json.m (+2395-1965)
  • (modified) clang/test/AST/ast-dump-decl-stmts.cpp (+4-4)
  • (modified) clang/test/AST/ast-dump-decl.c (+3-3)
  • (modified) clang/test/AST/ast-dump-decl.cpp (+447-506)
  • (modified) clang/test/AST/ast-dump-decl.m (+5-5)
  • (modified) clang/test/AST/ast-dump-decl.mm (+2-2)
  • (modified) clang/test/AST/ast-dump-default-arg-json.cpp (+2502-2091)
  • (modified) clang/test/AST/ast-dump-default-init-json.cpp (+1000-929)
  • (modified) clang/test/AST/ast-dump-expr-errors.cpp (+52-46)
  • (modified) clang/test/AST/ast-dump-expr-json.c (+6187-5550)
  • (modified) clang/test/AST/ast-dump-expr-json.cpp (+10359-9229)
  • (modified) clang/test/AST/ast-dump-expr-json.m (+5409-5048)
  • (modified) clang/test/AST/ast-dump-expr.c (+3-3)
  • (modified) clang/test/AST/ast-dump-expr.cpp (+10-10)
  • (modified) clang/test/AST/ast-dump-file-line-json.c (+399-310)
  • (modified) clang/test/AST/ast-dump-for-range-lifetime.cpp (+1684-347)
  • (modified) clang/test/AST/ast-dump-fpfeatures.cpp (+19-19)
  • (modified) clang/test/AST/ast-dump-funcs-json.cpp (+1568-1415)
  • (modified) clang/test/AST/ast-dump-funcs.cpp (+10-10)
  • (modified) clang/test/AST/ast-dump-functionprototype.cpp (+6-6)
  • (modified) clang/test/AST/ast-dump-if-json.cpp (+1266-1202)
  • (modified) clang/test/AST/ast-dump-invalid.cpp (+7-7)
  • (modified) clang/test/AST/ast-dump-lambda-body-not-duplicated.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-lambda.cpp (+275-273)
  • (modified) clang/test/AST/ast-dump-lookups.cpp (+8-8)
  • (modified) clang/test/AST/ast-dump-managed-var.cu (+4-4)
  • (modified) clang/test/AST/ast-dump-msp430-attr.c (+1-1)
  • (modified) clang/test/AST/ast-dump-openmp-atomic.c (+1-1)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant-varying-return.c (+44-44)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_10.c (+14-14)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_11.c (+34-34)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_12.c (+31-31)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_13.c (+3-3)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_2.c (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_3.c (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_4.c (+1-1)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_5.c (+6-6)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c (+31-18)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_7.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_8.c (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_9.c (+16-16)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_addr_1.c (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_namespace_1.cpp (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_nested.c (+5-5)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp (+59-59)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp (+15-15)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_2.cpp (+30-30)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_3.cpp (+370-233)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_4.cpp (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-cancel.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-cancellation-point.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-declare-variant-extensions.c (+15-15)
  • (modified) clang/test/AST/ast-dump-openmp-distribute-parallel-for-simd.c (+376-212)
  • (modified) clang/test/AST/ast-dump-openmp-distribute-parallel-for.c (+376-212)
  • (modified) clang/test/AST/ast-dump-openmp-distribute-simd.c (+206-206)
  • (modified) clang/test/AST/ast-dump-openmp-distribute.c (+55-55)
  • (modified) clang/test/AST/ast-dump-openmp-for-simd.c (+55-55)
  • (modified) clang/test/AST/ast-dump-openmp-for.c (+163-163)
  • (modified) clang/test/AST/ast-dump-openmp-ordered.c (+45-45)
  • (modified) clang/test/AST/ast-dump-openmp-parallel-for-simd.c (+216-216)
  • (modified) clang/test/AST/ast-dump-openmp-parallel-for.c (+216-216)
  • (modified) clang/test/AST/ast-dump-openmp-parallel-sections.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-parallel.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-simd.c (+206-206)
  • (modified) clang/test/AST/ast-dump-openmp-target-data.c (+1-1)
  • (modified) clang/test/AST/ast-dump-openmp-target-enter-data.c (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-target-exit-data.c (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-target-parallel-for-simd.c (+921-921)
  • (modified) clang/test/AST/ast-dump-openmp-target-parallel-for.c (+921-921)
  • (modified) clang/test/AST/ast-dump-openmp-target-parallel.c (+34-34)
  • (modified) clang/test/AST/ast-dump-openmp-target-simd.c (+461-461)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for-simd.c (+3521-1762)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for.c (+3521-1762)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams-distribute-simd.c (+921-921)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams-distribute.c (+921-921)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams.c (+44-44)
  • (modified) clang/test/AST/ast-dump-openmp-target-update.c (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-target.c (+12-12)
  • (modified) clang/test/AST/ast-dump-openmp-task.c (+6-6)
  • (modified) clang/test/AST/ast-dump-openmp-taskloop-simd.c (+266-266)
  • (modified) clang/test/AST/ast-dump-openmp-taskloop.c (+266-266)
  • (modified) clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for-simd.c (+3711-1952)
  • (modified) clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for.c (+3942-2183)
  • (modified) clang/test/AST/ast-dump-openmp-teams-distribute-simd.c (+1942-1223)
  • (modified) clang/test/AST/ast-dump-openmp-teams-distribute.c (+1942-1223)
  • (modified) clang/test/AST/ast-dump-openmp-teams.c (+35-35)
  • (modified) clang/test/AST/ast-dump-overloaded-operators.cpp (+22-22)
  • (modified) clang/test/AST/ast-dump-pack-indexing-crash.cpp (+5-5)
  • (modified) clang/test/AST/ast-dump-ppc-types.c (+3-3)
  • (modified) clang/test/AST/ast-dump-pragma-json.c (+515-485)
  • (modified) clang/test/AST/ast-dump-pragma-unroll.cpp (+4-4)
  • (modified) clang/test/AST/ast-dump-record-definition-data-json.cpp (+5985-5323)
  • (modified) clang/test/AST/ast-dump-records-json.cpp (+5115-4276)
  • (modified) clang/test/AST/ast-dump-records.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-recovery.c (+140-71)
  • (modified) clang/test/AST/ast-dump-recovery.cpp (+32-32)
  • (modified) clang/test/AST/ast-dump-riscv-attributes.cpp (+6-7)
  • (modified) clang/test/AST/ast-dump-sme-attributes.cpp (+42-32)
  • (modified) clang/test/AST/ast-dump-stmt-json.c (+6038-5480)
  • (modified) clang/test/AST/ast-dump-stmt-json.cpp (+8929-7229)
  • (modified) clang/test/AST/ast-dump-stmt-json.m (+877-773)
  • (modified) clang/test/AST/ast-dump-stmt.c (+64-42)
  • (modified) clang/test/AST/ast-dump-stmt.cpp (+27-19)
  • (modified) clang/test/AST/ast-dump-stmt.m (+1-1)
  • (modified) clang/test/AST/ast-dump-template-decls-json.cpp (+3417-3132)
  • (modified) clang/test/AST/ast-dump-template-decls.cpp (+61-40)
  • (modified) clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp (+528-3236)
  • (modified) clang/test/AST/ast-dump-template-name.cpp (+8-8)
  • (modified) clang/test/AST/ast-dump-templates.cpp (+8685-7944)
  • (modified) clang/test/AST/ast-dump-temporaries-json.cpp (+466-448)
  • (modified) clang/test/AST/ast-dump-traits.cpp (+51-35)
  • (modified) clang/test/AST/ast-dump-types-errors-json.cpp (+133-124)
  • (modified) clang/test/AST/ast-dump-types-json.cpp (+642-546)
  • (modified) clang/test/AST/ast-dump-using-template.cpp (+9-9)
  • (modified) clang/test/AST/ast-dump-using.cpp (+7-7)
  • (modified) clang/test/AST/ast-dump-wasm-attr-export.c (+12-12)
  • (modified) clang/test/AST/ast-dump-wasm-attr-import.c (+12-12)
  • (modified) clang/test/AST/attr-lifetime-capture-by.cpp (+12-12)
  • (modified) clang/test/AST/attr-swift_attr.m (+1-1)
  • (modified) clang/test/AST/attr-target-version.c (+3-4)
  • (modified) clang/test/AST/conditionally-trivial-smfs.cpp (+4-4)
  • (modified) clang/test/AST/dump.cpp (+26-26)
  • (modified) clang/test/AST/fixed_point.c (+168-168)
  • (modified) clang/test/AST/float16.cpp (+241-165)
  • (modified) clang/test/AST/ms-constexpr.cpp (+2-2)
  • (modified) clang/test/AST/multistep-explicit-cast-json.c (+698-626)
  • (modified) clang/test/AST/multistep-explicit-cast-json.cpp (+1731-1587)
  • (modified) clang/test/AST/new-unknown-type.cpp (+1-1)
  • (modified) clang/test/AST/nrvo.c (+2-2)
  • (modified) clang/test/AST/pr43983.cpp (+1-1)
  • (modified) clang/test/AST/pragma-attribute-cxx-subject-match-rules.cpp (+40-40)
  • (modified) clang/test/AST/pragma-attribute-objc-subject-match-rules.m (+6-6)
  • (modified) clang/test/AST/pragma-multiple-attributes-declspec.cpp (+2-2)
  • (modified) clang/test/AST/pragma-multiple-attributes.cpp (+4-4)
  • (modified) clang/unittests/AST/ASTTraverserTest.cpp (+4)
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 8ebabb2bde10d..b282f748a1426 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -11,6 +11,22 @@
 // similar to RecursiveASTVisitor.
 //
 //===----------------------------------------------------------------------===//
+//
+// Modifications to this file by SEI staff are copyright Carnegie Mellon
+// University and contributed under the Apache License v2.0 with LLVM
+// Exceptions.
+//
+// SEI Contributions are made with funding sand support from the Department of
+// Defense under Contract No. FA8702-15-D-0002 with Carnegie Mellon University
+// for the operation of the Software Engineering Institute, a federally funded
+// research and development center.
+//
+// The view, opinions, and/or findings contained in this material are those of
+// the author(s) and should not be construed as an official Government position,
+// policy, or decision, unless designated by other documentation.
+// DM24-0194
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_AST_ASTNODETRAVERSER_H
 #define LLVM_CLANG_AST_ASTNODETRAVERSER_H
@@ -177,14 +193,34 @@ class ASTNodeTraverser
     if (!SQT.Quals.hasQualifiers())
       return Visit(SQT.Ty);
 
-    getNodeDelegate().AddChild([=] {
+    // SEI: changed from default label to "qualTypeDetail"
+    getNodeDelegate().AddChild("qualTypeDetail", [this, T] {
       getNodeDelegate().Visit(T);
       Visit(T.split().Ty);
     });
+
+    // SEI function pointer support. this gets called whenever the three
+    // conditions are met:
+    // 1. the function pointer is not typedef'd
+    // 2. after Visit(VarDecl *) gets called
+    // 3. if VarDecl determines this is a function pointer
+    if (T->isFunctionPointerType()) {
+      // create as a child node to this type
+      getNodeDelegate().AddChild(
+          [=] { getNodeDelegate().Visit(T->getPointeeType()); });
+    }
+
+    // SEI: traverse PointerType information
+    if (T->isPointerType())
+      Visit(T->getPointeeType());
   }
 
+  // SEI: traverse ReturnType information
+  void VisitReturnType(QualType T) { getNodeDelegate().VisitReturnType(T); }
+
   void Visit(const Type *T) {
-    getNodeDelegate().AddChild([=] {
+    // SEI: renamed this from default label
+    getNodeDelegate().AddChild("typeDetails", [this, T] {
       getNodeDelegate().Visit(T);
       if (!T)
         return;
@@ -209,7 +245,8 @@ class ASTNodeTraverser
   }
 
   void Visit(const Attr *A) {
-    getNodeDelegate().AddChild([=] {
+    // SEI: renamed from default label
+    getNodeDelegate().AddChild("attrDetails", [this, A] {
       getNodeDelegate().Visit(A);
       ConstAttrVisitor<Derived>::Visit(A);
     });
@@ -416,8 +453,20 @@ class ASTNodeTraverser
     Visit(T->getSizeExpr());
   }
   void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); }
-  void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); }
+  void VisitFunctionType(const FunctionType *T) {
+
+    Visit(T->getReturnType());
+
+    // SEI: add functionDetails, incl. return type
+    getNodeDelegate().AddChild("functionDetails", [this, T] {
+      getNodeDelegate().VisitFunctionType(T);
+      getNodeDelegate().VisitReturnType(T->getReturnType());
+    });
+  }
+
   void VisitFunctionProtoType(const FunctionProtoType *T) {
+
+    // SEI: visit the function type. this will force the return type info too.
     VisitFunctionType(T);
     for (const QualType &PT : T->getParamTypes())
       Visit(PT);
@@ -585,6 +634,12 @@ class ASTNodeTraverser
       Visit(TSI->getTypeLoc());
     if (D->hasInit())
       Visit(D->getInit());
+
+    // SEI: if this is a function pointer, then we need to get the
+    // FunctionProtoType and then make add'l visits. if the FP is typedef'd,
+    // then this behavior occurs for us outside of Visit(VarDecl *)
+    //getNodeDelegate().Visit(D->getType(), true);
+    Visit(D->getType()); 
   }
 
   void VisitDecompositionDecl(const DecompositionDecl *D) {
diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h
index 570662b58ccf0..f20303f0509f0 100644
--- a/clang/include/clang/AST/JSONNodeDumper.h
+++ b/clang/include/clang/AST/JSONNodeDumper.h
@@ -10,6 +10,22 @@
 // a JSON.
 //
 //===----------------------------------------------------------------------===//
+//
+// Modifications to this file by SEI staff are copyright Carnegie Mellon
+// University and contributed under the Apache License v2.0 with LLVM
+// Exceptions.
+//
+// SEI Contributions are made with funding sand support from the Department of
+// Defense under Contract No. FA8702-15-D-0002 with Carnegie Mellon University
+// for the operation of the Software Engineering Institute, a federally funded
+// research and development center.
+//
+// The view, opinions, and/or findings contained in this material are those of
+// the author(s) and should not be construed as an official Government position,
+// policy, or decision, unless designated by other documentation.
+// DM24-0194
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H
 #define LLVM_CLANG_AST_JSONNODEDUMPER_H
@@ -26,6 +42,9 @@
 #include "clang/AST/Type.h"
 #include "llvm/Support/JSON.h"
 
+// SEI: added for caching addresses of certain visited nodes
+#include <unordered_set>
+
 namespace clang {
 
 class APValue;
@@ -111,8 +130,8 @@ class NodeStreamer {
 // Dumps AST nodes in JSON format. There is no implied stability for the
 // content or format of the dump between major releases of Clang, other than it
 // being valid JSON output. Further, there is no requirement that the
-// information dumped is a complete representation of the AST, only that the
-// information presented is correct.
+// information dumped be a complete representation of the AST, only that the
+// information presented be correct.
 class JSONNodeDumper
     : public ConstAttrVisitor<JSONNodeDumper>,
       public comments::ConstCommentVisitor<JSONNodeDumper, void,
@@ -132,6 +151,9 @@ class JSONNodeDumper
   StringRef LastLocFilename, LastLocPresumedFilename;
   unsigned LastLocLine, LastLocPresumedLine;
 
+  // SEI: caches addresses for QualType nodes that are duplicates
+  std::unordered_set<void *> AddressCache;
+
   using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>;
   using InnerCommentVisitor =
       comments::ConstCommentVisitor<JSONNodeDumper, void,
@@ -184,6 +206,18 @@ class JSONNodeDumper
 
   StringRef getCommentCommandName(unsigned CommandID) const;
 
+  /// SEI: simple cacher for addresses of nodes to reduce
+  /// bloat caused by SEI changes
+  /// Return True if it's already cached, otherwise false
+  bool cacheAddress(void *p) {
+    if (AddressCache.find(p) == AddressCache.end()) {
+      AddressCache.insert(p);
+      return false;
+    }
+
+    return true;
+  }
+
 public:
   JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
                  const PrintingPolicy &PrintPolicy,
@@ -196,6 +230,17 @@ class JSONNodeDumper
   void Visit(const Stmt *Node);
   void Visit(const Type *T);
   void Visit(QualType T);
+
+  // SEI: forwarding function to Visit(QualType T); so that it's applied here
+  // from a VarDecl call
+  void Visit(QualType T, bool isFromDecl);
+
+  // SEI: get specific details from the qual type
+  void VisitQualTypeDetails(QualType T);
+
+  // SEI: traverse ReturnType information
+  void VisitReturnType(QualType T);
+
   void Visit(const Decl *D);
   void Visit(TypeLoc TL);
 
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index 1917a8ac29f05..1340fdb4acb51 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -9,6 +9,22 @@
 // This file implements AST dumping of components of individual AST nodes.
 //
 //===----------------------------------------------------------------------===//
+//
+// Modifications to this file by SEI staff are copyright Carnegie Mellon
+// University and contributed under the Apache License v2.0 with LLVM
+// Exceptions.
+//
+// SEI Contributions are made with funding sand support from the Department of
+// Defense under Contract No. FA8702-15-D-0002 with Carnegie Mellon University
+// for the operation of the Software Engineering Institute, a federally funded
+// research and development center.
+//
+// The view, opinions, and/or findings contained in this material are those of
+// the author(s) and should not be construed as an official Government position,
+// policy, or decision, unless designated by other documentation.
+// DM24-0194
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_AST_TEXTNODEDUMPER_H
 #define LLVM_CLANG_AST_TEXTNODEDUMPER_H
@@ -181,8 +197,17 @@ class TextNodeDumper
 
   void Visit(QualType T);
 
+  // SEI: added to prevent this from being added whenever it comes from VarDecl
+  void Visit(QualType T, bool isFromDecl);
+
   void Visit(TypeLoc);
 
+  // SEI: added support for getting ReturnType information
+  void VisitReturnType(QualType T);
+
+  // SEI: added support for more QT details. it's a passthrough for this class
+  void VisitQualTypeDetails(QualType T) {}
+
   void Visit(const Decl *D);
 
   void Visit(const CXXCtorInitializer *Init);
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 64ddb1e739347..11cd21e844dba 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -70,6 +70,19 @@ void JSONNodeDumper::Visit(const Stmt *S) {
 }
 
 void JSONNodeDumper::Visit(const Type *T) {
+  // SEI: ensure FPTs are debloated. this can be expanded to ALL types, if
+  // desired
+  if (T && cacheAddress((void *)T)) {
+    // add this as a child to know that it's a Type
+    AddChild("typeDetails",
+             [=] { JOS.attribute("refId", createPointerRepresentation(T)); });
+
+    InnerTypeVisitor::Visit(T);
+    // SEI
+    VisitQualTypeDetails(T->getCanonicalTypeInternal());
+    return;
+  }
+
   JOS.attribute("id", createPointerRepresentation(T));
 
   if (!T)
@@ -86,15 +99,50 @@ void JSONNodeDumper::Visit(const Type *T) {
                       T->containsUnexpandedParameterPack());
   attributeOnlyIfTrue("isImported", T->isFromAST());
   InnerTypeVisitor::Visit(T);
+  // SEI
+  VisitQualTypeDetails(T->getCanonicalTypeInternal());
 }
 
 void JSONNodeDumper::Visit(QualType T) {
-  JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));
-  JOS.attribute("kind", "QualType");
-  JOS.attribute("type", createQualType(T));
-  JOS.attribute("qualifiers", T.split().Quals.getAsString());
+
+  // SEI: used AddChild to prevent qualType from being part added to a list
+  // JOS.attributeArray("qualTypes", [=] {
+
+  // SEI: force qualType into its own block, otherwise multiple Visits
+  // create a bunch of siblings, which is invalid JSON
+  JOS.attributeBegin("qualType");
+  JOS.objectBegin();
+
+  // SEI: cache visited addresses and add only its refId
+  // instead of the kind, type, quals, but leave the qual type details
+  // because those can differ among IDs
+  if (cacheAddress(T.getAsOpaquePtr())) {
+    JOS.attribute("refId", createPointerRepresentation(T.getAsOpaquePtr()));
+  } else {
+    JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));
+    JOS.attribute("kind", "QualType");
+    JOS.attribute("type", createQualType(T));
+    JOS.attribute("qualifiers", T.split().Quals.getAsString());
+  }
+
+  // SEI: get add'l info required for redemption analysis
+  // the qual type details differ even among cached references
+  VisitQualTypeDetails(T);
+
+  // SEI: if this is a pointer type, then recursively call ourselves
+  // until it's not
+  if (T->isPointerType())
+    Visit(T->getPointeeType());
+
+  JOS.objectEnd();
+  JOS.attributeEnd();
+  //} );
 }
 
+// SEI: added this as a forwarding function so that the TextNodeDumper
+// SEI: doesn't have this applied when coming from a VarDecl
+void JSONNodeDumper::Visit(QualType T, bool isFromDecl) { Visit(T); }
+
 void JSONNodeDumper::Visit(TypeLoc TL) {
   if (TL.isNull())
     return;
@@ -110,6 +158,64 @@ void JSONNodeDumper::Visit(TypeLoc TL) {
                       [TL, this] { writeSourceRange(TL.getSourceRange()); });
 }
 
+void JSONNodeDumper::VisitQualTypeDetails(QualType T) {
+  // SEI: get more detailed info on type. this info is not transferrable
+  // with the refId, so this must be called on every type even if that type
+  // has been cached
+  JOS.attributeBegin("qualDetails");
+  JOS.arrayBegin();
+
+  auto CT = T->getCanonicalTypeInternal();
+
+  if (CT->isStructureType())
+    JOS.value("struct");
+
+  if (CT->isNullPtrType())
+    JOS.value("null");
+  if (CT->isUndeducedType())
+    JOS.value("undeduced");
+
+  if (CT->isPointerType())
+    JOS.value("ptr");
+  if (CT->isVoidType())
+    JOS.value("void");
+
+  if (CT->isSignedIntegerType())
+    JOS.value("signed");
+  if (CT->isUnsignedIntegerType())
+    JOS.value("unsigned");
+  if (CT->isIntegerType())
+    JOS.value("integer");
+  if (CT->isFloatingType())
+    JOS.value("fpp");
+  if (CT->isEnumeralType())
+    JOS.value("enum");
+  if (CT->isUnionType())
+    JOS.value("union");
+  if (CT->isFunctionPointerType())
+    JOS.value("func_ptr");
+  if (CT->isTypedefNameType())
+    JOS.value("type_def");
+  if (CT->isArrayType())
+    JOS.value("array");
+
+  JOS.arrayEnd();
+  JOS.attributeEnd();
+}
+
+// SEI: capture the return info in a nested JSON block
+void JSONNodeDumper::VisitReturnType(QualType T) {
+  // using this function allows us to easily wrap just the returnType
+  // section into its own JSON block. if we do this in ASTNodeTraverser,
+  // then the TextNodeDumper works as expected but the JSONNodeDumper
+  // rolls all siblings into the returnType node with those siblings as child
+  // nodes
+
+  JOS.attributeObject("returnTypeDetail", [=] { Visit(T); });
+
+  // Visit(T);
+}
+
 void JSONNodeDumper::Visit(const Decl *D) {
   JOS.attribute("id", createPointerRepresentation(D));
 
@@ -174,6 +280,14 @@ void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
 
 void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
   JOS.attribute("kind", "CXXCtorInitializer");
+
+  // SEI: added id for
+  JOS.attribute("id", createPointerRepresentation(Init));
+
+  // SEI: added range for CXXCtorInitializers
+  JOS.attributeObject(
+      "range", [Init, this] { writeSourceRange(Init->getSourceRange()); });
+
   if (Init->isAnyMemberInitializer())
     JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember()));
   else if (Init->isBaseInitializer())
@@ -957,6 +1071,10 @@ void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) {
   attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate());
   attributeOnlyIfTrue("isBitfield", FD->isBitField());
   attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer());
+
+  // SEI: had to add this in b/c FieldDecls do not seem to call
+  // Visit(QualType)
+  Visit(FD->getType());
 }
 
 void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {
@@ -1350,6 +1468,8 @@ void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {
   case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;
   }
   attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating());
+  // SEI: this doesn't call VisitNamedDecl, so we force it
+  Visit(DRE->getType());
 }
 
 void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 6b524cfcd2d71..d295faa7f3442 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -242,6 +242,21 @@ void TextNodeDumper::Visit(QualType T) {
   OS << " " << T.split().Quals.getAsString();
 }
 
+// SEI: ignore this from being called whenever it's from a VarDecl
+// SEI: so we don't interfere with the normal text output
+void TextNodeDumper::Visit(QualType T, bool isFromDecl) {
+  if (!isFromDecl)
+    Visit(T);
+}
+
+void TextNodeDumper::VisitReturnType(QualType T) {
+  OS << "ReturnType";
+  dumpPointer(T.getAsOpaquePtr());
+  OS << " ";
+  dumpBareType(T, false);
+  OS << " " << T.split().Quals.getAsString();
+}
+
 void TextNodeDumper::Visit(TypeLoc TL) {
   if (!TL) {
     ColorScope Color(OS, ShowColors, NullColor);
diff --git a/clang/test/AST/ByteCode/builtin-constant-p.cpp b/clang/test/AST/ByteCode/builtin-constant-p.cpp
index 315a907949c34..9f5521590833d 100644
--- a/clang/test/AST/ByteCode/builtin-constant-p.cpp
+++ b/clang/test/AST/ByteCode/builtin-constant-p.cpp
@@ -140,11 +140,3 @@ void test17(void) {
   F("string literal" + 1); // both-warning {{adding}} \
                            // both-note {{use array indexing}}
 }
-
-/// FIXME
-static void foo(int i) __attribute__((__diagnose_if__(!__builtin_constant_p(i), "not constant", "error"))) // expected-note {{from}}
-{
-}
-static void bar(int i) {
-  foo(15); // expected-error {{not constant}}
-}
diff --git a/clang/test/AST/ByteCode/complex.cpp b/clang/test/AST/ByteCode/complex.cpp
index be10b3cfa53da..10ca82fbdc485 100644
--- a/clang/test/AST/ByteCode/complex.cpp
+++ b/clang/test/AST/ByteCode/complex.cpp
@@ -409,4 +409,4 @@ namespace ComplexConstexpr {
   static_assert(__real test6 == 5, "");
   static_assert(__imag test6 == 6, "");
   static_assert(&__imag test6 == &__real test6 + 1, "");
-}
+}
\ No newline at end of file
diff --git a/clang/test/AST/ByteCode/const-eval.c b/clang/test/AST/ByteCode/const-eval.c
index 3e228226ac8c1..eab14c08ec809 100644
--- a/clang/test/AST/ByteCode/const-eval.c
+++ b/clang/test/AST/ByteCode/const-eval.c
@@ -180,9 +180,6 @@ typedef __INTPTR_TYPE__ intptr_t;
 const intptr_t A = (intptr_t)(((int*) 0) + 1);
 const intptr_t B = (intptr_t)(((char*)0) + 3);
 _Static_assert(A > B, "");
-int * GH149500_p = &(*(int *)0x400);
-static const void *GH149500_q = &(*(const struct sysrq_key_op *)0);
-
 #else
 #error :(
 #endif
diff --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp
index 45dd4f528aefb..2856b872d44ab 100644
--- a/clang/test/AST/ByteCode/cxx23.cpp
+++ b/clang/test/AST/ByteCode/cxx23.cpp
@@ -369,26 +369,7 @@ namespace NestedUnions {
     return true;
   }
   static_assert(test_nested());
-}
-
-namespace UnionMemberCallDiags {
-  struct A { int n; };
-  struct B { A a; };
-  constexpr A a = (A() = B().a);
 
-  union C {
-    int n;
-    A a;
-  };
 
-  constexpr bool g() {
-    C c = {.n = 1};
-    c.a.operator=(B{2}.a); // all-note {{member call on member 'a' of union with active member 'n' is not allowed in a constant expression}}
-    return c.a.n == 2;
-  }
-  static_assert(g()); // all-error {{not an integral constant expression}} \
-                      // all-note {{in call to}}
 }
-
-
 #endif
diff --git a/clang/test/AST/ByteCode/placement-new.cpp b/clang/test/AST/ByteCode/placement-new.cpp
index b587cd6eaf89c..670def2d5870e 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -486,11 +486,3 @@ namespace bitcast {
   }
   static_assert(foo() == 0);
 }
-
-constexpr int modify_const_variable() {
-  const int a = 10;
-  new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}}
-  return a;
-}
-static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \
-                                        // both-note {{in call to}}
diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp
index 5ca3e2d12e2df..8925f2a2d0b67 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1839,4 +1839,4 @@ namespace DiamondDowncast {
   constexpr Top &top1 = (Middle1&)bottom;
   constexpr Middle2 &fail = (Middle2&)top1; // both-error {{must be initialized by a constant expression}} \
                                             // both-note {{cannot cast object of dynamic type 'const Bottom' to type 'Middle2'}}
-}
+}
\ No newline at end of file
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index f85194496942b..74fcfa6ac6129 100644
--- a/clang/test/AST/HLSL/ByteAddressBuff...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Aug 6, 2025

@llvm/pr-subscribers-clang

Author: Nicholas Reimer (sei-nreimer)

Changes

AST output modifications primarily focused on JSON enhancements for the SEI Redemption project. Some of the key changes are:

  1. Recursive Pointer Resolution
  • Modified the AST to accurately track multiple levels of pointer indirection during analysis
  1. Function Pointer Identification
  • Improved function pointer type identification handling, enabling correct resolution and analysis of function pointer assignments and calls within the AST
  1. QualType Enhancements
  • Updated QualType to better represent types with qualifiers such as const, volatile, and others
  1. QualDetails Addition
  • Introduced a new structure, QualDetails, to encapsulate additional metadata about type qualifiers, e.g., ptr, signed, float, struct, union, array, promotable, integer, func_ptr
  1. Return Type Information
  • Updated the AST to expose detailed return type information, similar to VarDecl
  1. JSON Debloating:
  • Reduced the size of JSON output by caching IDs and then using the refID key for referring back to the original ID
  1. Added Missing Range and ID for CXXCtorInitializer

Examples

// recursive pointer resolution
int ** c;

image

// function pointer information
long (*foo)(int (*)(short));

image

// return type information
int runFunctionTestA( char a );

image

// refID usage example. 
int a; // (not in image) first time encountering an int
int *b; // (not in image) first time encountering int *, but second time encountering int
int **c;  // first time encountering int **, but second time encountering int * and third time int

image


Patch is 9.88 MiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/152372.diff

174 Files Affected:

  • (modified) clang/include/clang/AST/ASTNodeTraverser.h (+59-4)
  • (modified) clang/include/clang/AST/JSONNodeDumper.h (+47-2)
  • (modified) clang/include/clang/AST/TextNodeDumper.h (+25)
  • (modified) clang/lib/AST/JSONNodeDumper.cpp (+124-4)
  • (modified) clang/lib/AST/TextNodeDumper.cpp (+15)
  • (modified) clang/test/AST/ByteCode/builtin-constant-p.cpp (-8)
  • (modified) clang/test/AST/ByteCode/complex.cpp (+1-1)
  • (modified) clang/test/AST/ByteCode/const-eval.c (-3)
  • (modified) clang/test/AST/ByteCode/cxx23.cpp (-19)
  • (modified) clang/test/AST/ByteCode/placement-new.cpp (-8)
  • (modified) clang/test/AST/ByteCode/records.cpp (+1-1)
  • (modified) clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl (+52-52)
  • (modified) clang/test/AST/HLSL/OutArgExpr.hlsl (+4-4)
  • (modified) clang/test/AST/HLSL/RootSignatures-AST.hlsl (+5-5)
  • (modified) clang/test/AST/HLSL/StructuredBuffers-AST.hlsl (+159-159)
  • (modified) clang/test/AST/HLSL/TypdefArrayParam.hlsl (+3-3)
  • (modified) clang/test/AST/HLSL/TypedBuffers-AST.hlsl (+112-112)
  • (modified) clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl (+161-8)
  • (modified) clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl (+10-12)
  • (modified) clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl (+6-6)
  • (modified) clang/test/AST/HLSL/packoffset.hlsl (+305-49)
  • (modified) clang/test/AST/HLSL/pch_hlsl_buffer.hlsl (+16-16)
  • (modified) clang/test/AST/HLSL/resource_binding_attr.hlsl (+192-24)
  • (modified) clang/test/AST/alignas_maybe_odr_cleanup.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-aarch64-sve-types.c (+15-15)
  • (modified) clang/test/AST/ast-dump-arm-attr.c (+1-1)
  • (modified) clang/test/AST/ast-dump-array.cpp (+60-4)
  • (modified) clang/test/AST/ast-dump-atomic-options.hip (+217-64)
  • (modified) clang/test/AST/ast-dump-attr-json.cpp (+654-531)
  • (modified) clang/test/AST/ast-dump-attr-type.cpp (+11-11)
  • (modified) clang/test/AST/ast-dump-attr.cpp (+331-298)
  • (modified) clang/test/AST/ast-dump-attr.m (+3-3)
  • (modified) clang/test/AST/ast-dump-c-attr.c (+13-11)
  • (modified) clang/test/AST/ast-dump-comment.cpp (+5-5)
  • (modified) clang/test/AST/ast-dump-concepts.cpp (+9-9)
  • (modified) clang/test/AST/ast-dump-constant-var.cu (+2-2)
  • (modified) clang/test/AST/ast-dump-coroutine.cpp (+343-67)
  • (modified) clang/test/AST/ast-dump-ctad-alias.cpp (+19-19)
  • (modified) clang/test/AST/ast-dump-decl-json.c (+1993-1650)
  • (modified) clang/test/AST/ast-dump-decl-json.m (+2395-1965)
  • (modified) clang/test/AST/ast-dump-decl-stmts.cpp (+4-4)
  • (modified) clang/test/AST/ast-dump-decl.c (+3-3)
  • (modified) clang/test/AST/ast-dump-decl.cpp (+447-506)
  • (modified) clang/test/AST/ast-dump-decl.m (+5-5)
  • (modified) clang/test/AST/ast-dump-decl.mm (+2-2)
  • (modified) clang/test/AST/ast-dump-default-arg-json.cpp (+2502-2091)
  • (modified) clang/test/AST/ast-dump-default-init-json.cpp (+1000-929)
  • (modified) clang/test/AST/ast-dump-expr-errors.cpp (+52-46)
  • (modified) clang/test/AST/ast-dump-expr-json.c (+6187-5550)
  • (modified) clang/test/AST/ast-dump-expr-json.cpp (+10359-9229)
  • (modified) clang/test/AST/ast-dump-expr-json.m (+5409-5048)
  • (modified) clang/test/AST/ast-dump-expr.c (+3-3)
  • (modified) clang/test/AST/ast-dump-expr.cpp (+10-10)
  • (modified) clang/test/AST/ast-dump-file-line-json.c (+399-310)
  • (modified) clang/test/AST/ast-dump-for-range-lifetime.cpp (+1684-347)
  • (modified) clang/test/AST/ast-dump-fpfeatures.cpp (+19-19)
  • (modified) clang/test/AST/ast-dump-funcs-json.cpp (+1568-1415)
  • (modified) clang/test/AST/ast-dump-funcs.cpp (+10-10)
  • (modified) clang/test/AST/ast-dump-functionprototype.cpp (+6-6)
  • (modified) clang/test/AST/ast-dump-if-json.cpp (+1266-1202)
  • (modified) clang/test/AST/ast-dump-invalid.cpp (+7-7)
  • (modified) clang/test/AST/ast-dump-lambda-body-not-duplicated.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-lambda.cpp (+275-273)
  • (modified) clang/test/AST/ast-dump-lookups.cpp (+8-8)
  • (modified) clang/test/AST/ast-dump-managed-var.cu (+4-4)
  • (modified) clang/test/AST/ast-dump-msp430-attr.c (+1-1)
  • (modified) clang/test/AST/ast-dump-openmp-atomic.c (+1-1)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant-varying-return.c (+44-44)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_10.c (+14-14)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_11.c (+34-34)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_12.c (+31-31)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_13.c (+3-3)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_2.c (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_3.c (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_4.c (+1-1)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_5.c (+6-6)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_6.c (+31-18)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_7.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_8.c (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_9.c (+16-16)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_addr_1.c (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_namespace_1.cpp (+4-4)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_nested.c (+5-5)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp (+59-59)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp (+15-15)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_2.cpp (+30-30)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_3.cpp (+370-233)
  • (modified) clang/test/AST/ast-dump-openmp-begin-declare-variant_template_4.cpp (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-cancel.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-cancellation-point.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-declare-variant-extensions.c (+15-15)
  • (modified) clang/test/AST/ast-dump-openmp-distribute-parallel-for-simd.c (+376-212)
  • (modified) clang/test/AST/ast-dump-openmp-distribute-parallel-for.c (+376-212)
  • (modified) clang/test/AST/ast-dump-openmp-distribute-simd.c (+206-206)
  • (modified) clang/test/AST/ast-dump-openmp-distribute.c (+55-55)
  • (modified) clang/test/AST/ast-dump-openmp-for-simd.c (+55-55)
  • (modified) clang/test/AST/ast-dump-openmp-for.c (+163-163)
  • (modified) clang/test/AST/ast-dump-openmp-ordered.c (+45-45)
  • (modified) clang/test/AST/ast-dump-openmp-parallel-for-simd.c (+216-216)
  • (modified) clang/test/AST/ast-dump-openmp-parallel-for.c (+216-216)
  • (modified) clang/test/AST/ast-dump-openmp-parallel-sections.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-parallel.c (+2-2)
  • (modified) clang/test/AST/ast-dump-openmp-simd.c (+206-206)
  • (modified) clang/test/AST/ast-dump-openmp-target-data.c (+1-1)
  • (modified) clang/test/AST/ast-dump-openmp-target-enter-data.c (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-target-exit-data.c (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-target-parallel-for-simd.c (+921-921)
  • (modified) clang/test/AST/ast-dump-openmp-target-parallel-for.c (+921-921)
  • (modified) clang/test/AST/ast-dump-openmp-target-parallel.c (+34-34)
  • (modified) clang/test/AST/ast-dump-openmp-target-simd.c (+461-461)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for-simd.c (+3521-1762)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams-distribute-parallel-for.c (+3521-1762)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams-distribute-simd.c (+921-921)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams-distribute.c (+921-921)
  • (modified) clang/test/AST/ast-dump-openmp-target-teams.c (+44-44)
  • (modified) clang/test/AST/ast-dump-openmp-target-update.c (+7-7)
  • (modified) clang/test/AST/ast-dump-openmp-target.c (+12-12)
  • (modified) clang/test/AST/ast-dump-openmp-task.c (+6-6)
  • (modified) clang/test/AST/ast-dump-openmp-taskloop-simd.c (+266-266)
  • (modified) clang/test/AST/ast-dump-openmp-taskloop.c (+266-266)
  • (modified) clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for-simd.c (+3711-1952)
  • (modified) clang/test/AST/ast-dump-openmp-teams-distribute-parallel-for.c (+3942-2183)
  • (modified) clang/test/AST/ast-dump-openmp-teams-distribute-simd.c (+1942-1223)
  • (modified) clang/test/AST/ast-dump-openmp-teams-distribute.c (+1942-1223)
  • (modified) clang/test/AST/ast-dump-openmp-teams.c (+35-35)
  • (modified) clang/test/AST/ast-dump-overloaded-operators.cpp (+22-22)
  • (modified) clang/test/AST/ast-dump-pack-indexing-crash.cpp (+5-5)
  • (modified) clang/test/AST/ast-dump-ppc-types.c (+3-3)
  • (modified) clang/test/AST/ast-dump-pragma-json.c (+515-485)
  • (modified) clang/test/AST/ast-dump-pragma-unroll.cpp (+4-4)
  • (modified) clang/test/AST/ast-dump-record-definition-data-json.cpp (+5985-5323)
  • (modified) clang/test/AST/ast-dump-records-json.cpp (+5115-4276)
  • (modified) clang/test/AST/ast-dump-records.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-recovery.c (+140-71)
  • (modified) clang/test/AST/ast-dump-recovery.cpp (+32-32)
  • (modified) clang/test/AST/ast-dump-riscv-attributes.cpp (+6-7)
  • (modified) clang/test/AST/ast-dump-sme-attributes.cpp (+42-32)
  • (modified) clang/test/AST/ast-dump-stmt-json.c (+6038-5480)
  • (modified) clang/test/AST/ast-dump-stmt-json.cpp (+8929-7229)
  • (modified) clang/test/AST/ast-dump-stmt-json.m (+877-773)
  • (modified) clang/test/AST/ast-dump-stmt.c (+64-42)
  • (modified) clang/test/AST/ast-dump-stmt.cpp (+27-19)
  • (modified) clang/test/AST/ast-dump-stmt.m (+1-1)
  • (modified) clang/test/AST/ast-dump-template-decls-json.cpp (+3417-3132)
  • (modified) clang/test/AST/ast-dump-template-decls.cpp (+61-40)
  • (modified) clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp (+528-3236)
  • (modified) clang/test/AST/ast-dump-template-name.cpp (+8-8)
  • (modified) clang/test/AST/ast-dump-templates.cpp (+8685-7944)
  • (modified) clang/test/AST/ast-dump-temporaries-json.cpp (+466-448)
  • (modified) clang/test/AST/ast-dump-traits.cpp (+51-35)
  • (modified) clang/test/AST/ast-dump-types-errors-json.cpp (+133-124)
  • (modified) clang/test/AST/ast-dump-types-json.cpp (+642-546)
  • (modified) clang/test/AST/ast-dump-using-template.cpp (+9-9)
  • (modified) clang/test/AST/ast-dump-using.cpp (+7-7)
  • (modified) clang/test/AST/ast-dump-wasm-attr-export.c (+12-12)
  • (modified) clang/test/AST/ast-dump-wasm-attr-import.c (+12-12)
  • (modified) clang/test/AST/attr-lifetime-capture-by.cpp (+12-12)
  • (modified) clang/test/AST/attr-swift_attr.m (+1-1)
  • (modified) clang/test/AST/attr-target-version.c (+3-4)
  • (modified) clang/test/AST/conditionally-trivial-smfs.cpp (+4-4)
  • (modified) clang/test/AST/dump.cpp (+26-26)
  • (modified) clang/test/AST/fixed_point.c (+168-168)
  • (modified) clang/test/AST/float16.cpp (+241-165)
  • (modified) clang/test/AST/ms-constexpr.cpp (+2-2)
  • (modified) clang/test/AST/multistep-explicit-cast-json.c (+698-626)
  • (modified) clang/test/AST/multistep-explicit-cast-json.cpp (+1731-1587)
  • (modified) clang/test/AST/new-unknown-type.cpp (+1-1)
  • (modified) clang/test/AST/nrvo.c (+2-2)
  • (modified) clang/test/AST/pr43983.cpp (+1-1)
  • (modified) clang/test/AST/pragma-attribute-cxx-subject-match-rules.cpp (+40-40)
  • (modified) clang/test/AST/pragma-attribute-objc-subject-match-rules.m (+6-6)
  • (modified) clang/test/AST/pragma-multiple-attributes-declspec.cpp (+2-2)
  • (modified) clang/test/AST/pragma-multiple-attributes.cpp (+4-4)
  • (modified) clang/unittests/AST/ASTTraverserTest.cpp (+4)
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 8ebabb2bde10d..b282f748a1426 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -11,6 +11,22 @@
 // similar to RecursiveASTVisitor.
 //
 //===----------------------------------------------------------------------===//
+//
+// Modifications to this file by SEI staff are copyright Carnegie Mellon
+// University and contributed under the Apache License v2.0 with LLVM
+// Exceptions.
+//
+// SEI Contributions are made with funding sand support from the Department of
+// Defense under Contract No. FA8702-15-D-0002 with Carnegie Mellon University
+// for the operation of the Software Engineering Institute, a federally funded
+// research and development center.
+//
+// The view, opinions, and/or findings contained in this material are those of
+// the author(s) and should not be construed as an official Government position,
+// policy, or decision, unless designated by other documentation.
+// DM24-0194
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_AST_ASTNODETRAVERSER_H
 #define LLVM_CLANG_AST_ASTNODETRAVERSER_H
@@ -177,14 +193,34 @@ class ASTNodeTraverser
     if (!SQT.Quals.hasQualifiers())
       return Visit(SQT.Ty);
 
-    getNodeDelegate().AddChild([=] {
+    // SEI: changed from default label to "qualTypeDetail"
+    getNodeDelegate().AddChild("qualTypeDetail", [this, T] {
       getNodeDelegate().Visit(T);
       Visit(T.split().Ty);
     });
+
+    // SEI function pointer support. this gets called whenever the three
+    // conditions are met:
+    // 1. the function pointer is not typedef'd
+    // 2. after Visit(VarDecl *) gets called
+    // 3. if VarDecl determines this is a function pointer
+    if (T->isFunctionPointerType()) {
+      // create as a child node to this type
+      getNodeDelegate().AddChild(
+          [=] { getNodeDelegate().Visit(T->getPointeeType()); });
+    }
+
+    // SEI: traverse PointerType information
+    if (T->isPointerType())
+      Visit(T->getPointeeType());
   }
 
+  // SEI: traverse ReturnType information
+  void VisitReturnType(QualType T) { getNodeDelegate().VisitReturnType(T); }
+
   void Visit(const Type *T) {
-    getNodeDelegate().AddChild([=] {
+    // SEI: renamed this from default label
+    getNodeDelegate().AddChild("typeDetails", [this, T] {
       getNodeDelegate().Visit(T);
       if (!T)
         return;
@@ -209,7 +245,8 @@ class ASTNodeTraverser
   }
 
   void Visit(const Attr *A) {
-    getNodeDelegate().AddChild([=] {
+    // SEI: renamed from default label
+    getNodeDelegate().AddChild("attrDetails", [this, A] {
       getNodeDelegate().Visit(A);
       ConstAttrVisitor<Derived>::Visit(A);
     });
@@ -416,8 +453,20 @@ class ASTNodeTraverser
     Visit(T->getSizeExpr());
   }
   void VisitVectorType(const VectorType *T) { Visit(T->getElementType()); }
-  void VisitFunctionType(const FunctionType *T) { Visit(T->getReturnType()); }
+  void VisitFunctionType(const FunctionType *T) {
+
+    Visit(T->getReturnType());
+
+    // SEI: add functionDetails, incl. return type
+    getNodeDelegate().AddChild("functionDetails", [this, T] {
+      getNodeDelegate().VisitFunctionType(T);
+      getNodeDelegate().VisitReturnType(T->getReturnType());
+    });
+  }
+
   void VisitFunctionProtoType(const FunctionProtoType *T) {
+
+    // SEI: visit the function type. this will force the return type info too.
     VisitFunctionType(T);
     for (const QualType &PT : T->getParamTypes())
       Visit(PT);
@@ -585,6 +634,12 @@ class ASTNodeTraverser
       Visit(TSI->getTypeLoc());
     if (D->hasInit())
       Visit(D->getInit());
+
+    // SEI: if this is a function pointer, then we need to get the
+    // FunctionProtoType and then make add'l visits. if the FP is typedef'd,
+    // then this behavior occurs for us outside of Visit(VarDecl *)
+    //getNodeDelegate().Visit(D->getType(), true);
+    Visit(D->getType()); 
   }
 
   void VisitDecompositionDecl(const DecompositionDecl *D) {
diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h
index 570662b58ccf0..f20303f0509f0 100644
--- a/clang/include/clang/AST/JSONNodeDumper.h
+++ b/clang/include/clang/AST/JSONNodeDumper.h
@@ -10,6 +10,22 @@
 // a JSON.
 //
 //===----------------------------------------------------------------------===//
+//
+// Modifications to this file by SEI staff are copyright Carnegie Mellon
+// University and contributed under the Apache License v2.0 with LLVM
+// Exceptions.
+//
+// SEI Contributions are made with funding sand support from the Department of
+// Defense under Contract No. FA8702-15-D-0002 with Carnegie Mellon University
+// for the operation of the Software Engineering Institute, a federally funded
+// research and development center.
+//
+// The view, opinions, and/or findings contained in this material are those of
+// the author(s) and should not be construed as an official Government position,
+// policy, or decision, unless designated by other documentation.
+// DM24-0194
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H
 #define LLVM_CLANG_AST_JSONNODEDUMPER_H
@@ -26,6 +42,9 @@
 #include "clang/AST/Type.h"
 #include "llvm/Support/JSON.h"
 
+// SEI: added for caching addresses of certain visited nodes
+#include <unordered_set>
+
 namespace clang {
 
 class APValue;
@@ -111,8 +130,8 @@ class NodeStreamer {
 // Dumps AST nodes in JSON format. There is no implied stability for the
 // content or format of the dump between major releases of Clang, other than it
 // being valid JSON output. Further, there is no requirement that the
-// information dumped is a complete representation of the AST, only that the
-// information presented is correct.
+// information dumped be a complete representation of the AST, only that the
+// information presented be correct.
 class JSONNodeDumper
     : public ConstAttrVisitor<JSONNodeDumper>,
       public comments::ConstCommentVisitor<JSONNodeDumper, void,
@@ -132,6 +151,9 @@ class JSONNodeDumper
   StringRef LastLocFilename, LastLocPresumedFilename;
   unsigned LastLocLine, LastLocPresumedLine;
 
+  // SEI: caches addresses for QualType nodes that are duplicates
+  std::unordered_set<void *> AddressCache;
+
   using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>;
   using InnerCommentVisitor =
       comments::ConstCommentVisitor<JSONNodeDumper, void,
@@ -184,6 +206,18 @@ class JSONNodeDumper
 
   StringRef getCommentCommandName(unsigned CommandID) const;
 
+  /// SEI: simple cacher for addresses of nodes to reduce
+  /// bloat caused by SEI changes
+  /// Return True if it's already cached, otherwise false
+  bool cacheAddress(void *p) {
+    if (AddressCache.find(p) == AddressCache.end()) {
+      AddressCache.insert(p);
+      return false;
+    }
+
+    return true;
+  }
+
 public:
   JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
                  const PrintingPolicy &PrintPolicy,
@@ -196,6 +230,17 @@ class JSONNodeDumper
   void Visit(const Stmt *Node);
   void Visit(const Type *T);
   void Visit(QualType T);
+
+  // SEI: forwarding function to Visit(QualType T); so that it's applied here
+  // from a VarDecl call
+  void Visit(QualType T, bool isFromDecl);
+
+  // SEI: get specific details from the qual type
+  void VisitQualTypeDetails(QualType T);
+
+  // SEI: traverse ReturnType information
+  void VisitReturnType(QualType T);
+
   void Visit(const Decl *D);
   void Visit(TypeLoc TL);
 
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index 1917a8ac29f05..1340fdb4acb51 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -9,6 +9,22 @@
 // This file implements AST dumping of components of individual AST nodes.
 //
 //===----------------------------------------------------------------------===//
+//
+// Modifications to this file by SEI staff are copyright Carnegie Mellon
+// University and contributed under the Apache License v2.0 with LLVM
+// Exceptions.
+//
+// SEI Contributions are made with funding sand support from the Department of
+// Defense under Contract No. FA8702-15-D-0002 with Carnegie Mellon University
+// for the operation of the Software Engineering Institute, a federally funded
+// research and development center.
+//
+// The view, opinions, and/or findings contained in this material are those of
+// the author(s) and should not be construed as an official Government position,
+// policy, or decision, unless designated by other documentation.
+// DM24-0194
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CLANG_AST_TEXTNODEDUMPER_H
 #define LLVM_CLANG_AST_TEXTNODEDUMPER_H
@@ -181,8 +197,17 @@ class TextNodeDumper
 
   void Visit(QualType T);
 
+  // SEI: added to prevent this from being added whenever it comes from VarDecl
+  void Visit(QualType T, bool isFromDecl);
+
   void Visit(TypeLoc);
 
+  // SEI: added support for getting ReturnType information
+  void VisitReturnType(QualType T);
+
+  // SEI: added support for more QT details. it's a passthrough for this class
+  void VisitQualTypeDetails(QualType T) {}
+
   void Visit(const Decl *D);
 
   void Visit(const CXXCtorInitializer *Init);
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 64ddb1e739347..11cd21e844dba 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -70,6 +70,19 @@ void JSONNodeDumper::Visit(const Stmt *S) {
 }
 
 void JSONNodeDumper::Visit(const Type *T) {
+  // SEI: ensure FPTs are debloated. this can be expanded to ALL types, if
+  // desired
+  if (T && cacheAddress((void *)T)) {
+    // add this as a child to know that it's a Type
+    AddChild("typeDetails",
+             [=] { JOS.attribute("refId", createPointerRepresentation(T)); });
+
+    InnerTypeVisitor::Visit(T);
+    // SEI
+    VisitQualTypeDetails(T->getCanonicalTypeInternal());
+    return;
+  }
+
   JOS.attribute("id", createPointerRepresentation(T));
 
   if (!T)
@@ -86,15 +99,50 @@ void JSONNodeDumper::Visit(const Type *T) {
                       T->containsUnexpandedParameterPack());
   attributeOnlyIfTrue("isImported", T->isFromAST());
   InnerTypeVisitor::Visit(T);
+  // SEI
+  VisitQualTypeDetails(T->getCanonicalTypeInternal());
 }
 
 void JSONNodeDumper::Visit(QualType T) {
-  JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));
-  JOS.attribute("kind", "QualType");
-  JOS.attribute("type", createQualType(T));
-  JOS.attribute("qualifiers", T.split().Quals.getAsString());
+
+  // SEI: used AddChild to prevent qualType from being part added to a list
+  // JOS.attributeArray("qualTypes", [=] {
+
+  // SEI: force qualType into its own block, otherwise multiple Visits
+  // create a bunch of siblings, which is invalid JSON
+  JOS.attributeBegin("qualType");
+  JOS.objectBegin();
+
+  // SEI: cache visited addresses and add only its refId
+  // instead of the kind, type, quals, but leave the qual type details
+  // because those can differ among IDs
+  if (cacheAddress(T.getAsOpaquePtr())) {
+    JOS.attribute("refId", createPointerRepresentation(T.getAsOpaquePtr()));
+  } else {
+    JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr()));
+    JOS.attribute("kind", "QualType");
+    JOS.attribute("type", createQualType(T));
+    JOS.attribute("qualifiers", T.split().Quals.getAsString());
+  }
+
+  // SEI: get add'l info required for redemption analysis
+  // the qual type details differ even among cached references
+  VisitQualTypeDetails(T);
+
+  // SEI: if this is a pointer type, then recursively call ourselves
+  // until it's not
+  if (T->isPointerType())
+    Visit(T->getPointeeType());
+
+  JOS.objectEnd();
+  JOS.attributeEnd();
+  //} );
 }
 
+// SEI: added this as a forwarding function so that the TextNodeDumper
+// SEI: doesn't have this applied when coming from a VarDecl
+void JSONNodeDumper::Visit(QualType T, bool isFromDecl) { Visit(T); }
+
 void JSONNodeDumper::Visit(TypeLoc TL) {
   if (TL.isNull())
     return;
@@ -110,6 +158,64 @@ void JSONNodeDumper::Visit(TypeLoc TL) {
                       [TL, this] { writeSourceRange(TL.getSourceRange()); });
 }
 
+void JSONNodeDumper::VisitQualTypeDetails(QualType T) {
+  // SEI: get more detailed info on type. this info is not transferrable
+  // with the refId, so this must be called on every type even if that type
+  // has been cached
+  JOS.attributeBegin("qualDetails");
+  JOS.arrayBegin();
+
+  auto CT = T->getCanonicalTypeInternal();
+
+  if (CT->isStructureType())
+    JOS.value("struct");
+
+  if (CT->isNullPtrType())
+    JOS.value("null");
+  if (CT->isUndeducedType())
+    JOS.value("undeduced");
+
+  if (CT->isPointerType())
+    JOS.value("ptr");
+  if (CT->isVoidType())
+    JOS.value("void");
+
+  if (CT->isSignedIntegerType())
+    JOS.value("signed");
+  if (CT->isUnsignedIntegerType())
+    JOS.value("unsigned");
+  if (CT->isIntegerType())
+    JOS.value("integer");
+  if (CT->isFloatingType())
+    JOS.value("fpp");
+  if (CT->isEnumeralType())
+    JOS.value("enum");
+  if (CT->isUnionType())
+    JOS.value("union");
+  if (CT->isFunctionPointerType())
+    JOS.value("func_ptr");
+  if (CT->isTypedefNameType())
+    JOS.value("type_def");
+  if (CT->isArrayType())
+    JOS.value("array");
+
+  JOS.arrayEnd();
+  JOS.attributeEnd();
+}
+
+// SEI: capture the return info in a nested JSON block
+void JSONNodeDumper::VisitReturnType(QualType T) {
+  // using this function allows us to easily wrap just the returnType
+  // section into its own JSON block. if we do this in ASTNodeTraverser,
+  // then the TextNodeDumper works as expected but the JSONNodeDumper
+  // rolls all siblings into the returnType node with those siblings as child
+  // nodes
+
+  JOS.attributeObject("returnTypeDetail", [=] { Visit(T); });
+
+  // Visit(T);
+}
+
 void JSONNodeDumper::Visit(const Decl *D) {
   JOS.attribute("id", createPointerRepresentation(D));
 
@@ -174,6 +280,14 @@ void JSONNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
 
 void JSONNodeDumper::Visit(const CXXCtorInitializer *Init) {
   JOS.attribute("kind", "CXXCtorInitializer");
+
+  // SEI: added id for
+  JOS.attribute("id", createPointerRepresentation(Init));
+
+  // SEI: added range for CXXCtorInitializers
+  JOS.attributeObject(
+      "range", [Init, this] { writeSourceRange(Init->getSourceRange()); });
+
   if (Init->isAnyMemberInitializer())
     JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember()));
   else if (Init->isBaseInitializer())
@@ -957,6 +1071,10 @@ void JSONNodeDumper::VisitFieldDecl(const FieldDecl *FD) {
   attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate());
   attributeOnlyIfTrue("isBitfield", FD->isBitField());
   attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer());
+
+  // SEI: had to add this in b/c FieldDecls do not seem to call
+  // Visit(QualType)
+  Visit(FD->getType());
 }
 
 void JSONNodeDumper::VisitFunctionDecl(const FunctionDecl *FD) {
@@ -1350,6 +1468,8 @@ void JSONNodeDumper::VisitDeclRefExpr(const DeclRefExpr *DRE) {
   case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break;
   }
   attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating());
+  // SEI: this doesn't call VisitNamedDecl, so we force it
+  Visit(DRE->getType());
 }
 
 void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 6b524cfcd2d71..d295faa7f3442 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -242,6 +242,21 @@ void TextNodeDumper::Visit(QualType T) {
   OS << " " << T.split().Quals.getAsString();
 }
 
+// SEI: ignore this from being called whenever it's from a VarDecl
+// SEI: so we don't interfere with the normal text output
+void TextNodeDumper::Visit(QualType T, bool isFromDecl) {
+  if (!isFromDecl)
+    Visit(T);
+}
+
+void TextNodeDumper::VisitReturnType(QualType T) {
+  OS << "ReturnType";
+  dumpPointer(T.getAsOpaquePtr());
+  OS << " ";
+  dumpBareType(T, false);
+  OS << " " << T.split().Quals.getAsString();
+}
+
 void TextNodeDumper::Visit(TypeLoc TL) {
   if (!TL) {
     ColorScope Color(OS, ShowColors, NullColor);
diff --git a/clang/test/AST/ByteCode/builtin-constant-p.cpp b/clang/test/AST/ByteCode/builtin-constant-p.cpp
index 315a907949c34..9f5521590833d 100644
--- a/clang/test/AST/ByteCode/builtin-constant-p.cpp
+++ b/clang/test/AST/ByteCode/builtin-constant-p.cpp
@@ -140,11 +140,3 @@ void test17(void) {
   F("string literal" + 1); // both-warning {{adding}} \
                            // both-note {{use array indexing}}
 }
-
-/// FIXME
-static void foo(int i) __attribute__((__diagnose_if__(!__builtin_constant_p(i), "not constant", "error"))) // expected-note {{from}}
-{
-}
-static void bar(int i) {
-  foo(15); // expected-error {{not constant}}
-}
diff --git a/clang/test/AST/ByteCode/complex.cpp b/clang/test/AST/ByteCode/complex.cpp
index be10b3cfa53da..10ca82fbdc485 100644
--- a/clang/test/AST/ByteCode/complex.cpp
+++ b/clang/test/AST/ByteCode/complex.cpp
@@ -409,4 +409,4 @@ namespace ComplexConstexpr {
   static_assert(__real test6 == 5, "");
   static_assert(__imag test6 == 6, "");
   static_assert(&__imag test6 == &__real test6 + 1, "");
-}
+}
\ No newline at end of file
diff --git a/clang/test/AST/ByteCode/const-eval.c b/clang/test/AST/ByteCode/const-eval.c
index 3e228226ac8c1..eab14c08ec809 100644
--- a/clang/test/AST/ByteCode/const-eval.c
+++ b/clang/test/AST/ByteCode/const-eval.c
@@ -180,9 +180,6 @@ typedef __INTPTR_TYPE__ intptr_t;
 const intptr_t A = (intptr_t)(((int*) 0) + 1);
 const intptr_t B = (intptr_t)(((char*)0) + 3);
 _Static_assert(A > B, "");
-int * GH149500_p = &(*(int *)0x400);
-static const void *GH149500_q = &(*(const struct sysrq_key_op *)0);
-
 #else
 #error :(
 #endif
diff --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp
index 45dd4f528aefb..2856b872d44ab 100644
--- a/clang/test/AST/ByteCode/cxx23.cpp
+++ b/clang/test/AST/ByteCode/cxx23.cpp
@@ -369,26 +369,7 @@ namespace NestedUnions {
     return true;
   }
   static_assert(test_nested());
-}
-
-namespace UnionMemberCallDiags {
-  struct A { int n; };
-  struct B { A a; };
-  constexpr A a = (A() = B().a);
 
-  union C {
-    int n;
-    A a;
-  };
 
-  constexpr bool g() {
-    C c = {.n = 1};
-    c.a.operator=(B{2}.a); // all-note {{member call on member 'a' of union with active member 'n' is not allowed in a constant expression}}
-    return c.a.n == 2;
-  }
-  static_assert(g()); // all-error {{not an integral constant expression}} \
-                      // all-note {{in call to}}
 }
-
-
 #endif
diff --git a/clang/test/AST/ByteCode/placement-new.cpp b/clang/test/AST/ByteCode/placement-new.cpp
index b587cd6eaf89c..670def2d5870e 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -486,11 +486,3 @@ namespace bitcast {
   }
   static_assert(foo() == 0);
 }
-
-constexpr int modify_const_variable() {
-  const int a = 10;
-  new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}}
-  return a;
-}
-static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \
-                                        // both-note {{in call to}}
diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp
index 5ca3e2d12e2df..8925f2a2d0b67 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1839,4 +1839,4 @@ namespace DiamondDowncast {
   constexpr Top &top1 = (Middle1&)bottom;
   constexpr Middle2 &fail = (Middle2&)top1; // both-error {{must be initialized by a constant expression}} \
                                             // both-note {{cannot cast object of dynamic type 'const Bottom' to type 'Middle2'}}
-}
+}
\ No newline at end of file
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index f85194496942b..74fcfa6ac6129 100644
--- a/clang/test/AST/HLSL/ByteAddressBuff...
[truncated]

Copy link
Collaborator

@jrtc27 jrtc27 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having all these SEI comments isn't going to fly. Nor is deleting bits of existing tests. On top of that, if you're wanting to make significant changes to the AST, that may warrant an RFC. Not to mention that "one commit that does 7 enumerated things" is not a good way to seek review of things if it can be avoided.

@AaronBallman AaronBallman self-requested a review August 7, 2025 17:26
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the comments from @jrtc27, the copyright notices may also be problematic (I commented in the PR on it).

I realize you've got constraints on your end that may make this impractical, but from our end what we'd like to see is:

  • The SEI comments should be removed, probably including the copyright notices
  • Any existing test code that you've removed needs to be restored; it's fine to modify tests to expect new output (that's normal) but it's generally not okay to remove existing test coverage without justifying why it's safe to remove
  • Splitting the PR up into multiple logical changes so it's less massive

Comment on lines +15 to +17
// Modifications to this file by SEI staff are copyright Carnegie Mellon
// University and contributed under the Apache License v2.0 with LLVM
// Exceptions.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CC @llvm-beanz regarding licensing concerns. Pretty sure this is not something we can accept per: https://llvm.org/docs/DeveloperPolicy.html#embedded-copyright-or-contributed-by-statements

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed. We do not accept embedded copyright notices.

// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:18> col:23 'float'
// CHECK-NEXT: ParmVarDecl 0x{{[^ ]*}} <col:25, col:31> col:29 'int' cinit
// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:31> 'int' 12
// CHECK: ParmVarDecl 0x{{[^ ]*}} <col:25, col:31> col:29 'int' cinit
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're prefer to keep the CHECK-NEXT lines whenever possible because otherwise the test failures become harder to reason about when someone breaks the functionality (it also makes it easier to hide test failures).

Comment on lines +9 to +13
// CHECK-NEXT: `-typeDetails: ParenType {{.*}}
// CHECK-NEXT: `-typeDetails: FunctionProtoType {{.*}} 'void () noexcept(10 > 5)' exceptionspec_noexcept_true cdecl
// CHECK-NEXT: |-NoexceptExpr: ConstantExpr {{.*}} 'bool'
// CHECK-NEXT: | `-value: Int 1
// CHECK-NEXT: `-BuiltinType {{.*}} 'void'
// CHECK: `-functionDetails: cdeclReturnType {{.*}} 'void'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain a bit about how this helps folks with the textual dumps? It looks like this is more for folks trying to script the results, but those uses should be using the JSON dump output because that's actually structured output. The text node dumper is mostly used by folks who are in a debugger and want more information about what's being debugged, and for them these extra "details" bits are likely to be noise.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tried to leave the text dumps alone as much as possible. Unfortunately, to get some of the additional information that we needed, we had to update ASTNodeTraverser. Those changes mean that TextNodeDumper now receives the additional information as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree the changes to the Textual AST dump don't seem helpful for its intended purpose.

You could make your changes to the JSON AST node dumper only. Even then, a lot of the new information looks like it wouldn't be very interesting to most users and is quite extra verbose, so it could be hidden behind a flag.

// University and contributed under the Apache License v2.0 with LLVM
// Exceptions.
//
// SEI Contributions are made with funding sand support from the Department of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// SEI Contributions are made with funding sand support from the Department of
// SEI Contributions are made with funding and support from the Department of

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo, but we probably can't allow this copyright notice anyway, per project policy.

Comment on lines +9 to +13
// CHECK-NEXT: `-typeDetails: ParenType {{.*}}
// CHECK-NEXT: `-typeDetails: FunctionProtoType {{.*}} 'void () noexcept(10 > 5)' exceptionspec_noexcept_true cdecl
// CHECK-NEXT: |-NoexceptExpr: ConstantExpr {{.*}} 'bool'
// CHECK-NEXT: | `-value: Int 1
// CHECK-NEXT: `-BuiltinType {{.*}} 'void'
// CHECK: `-functionDetails: cdeclReturnType {{.*}} 'void'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree the changes to the Textual AST dump don't seem helpful for its intended purpose.

You could make your changes to the JSON AST node dumper only. Even then, a lot of the new information looks like it wouldn't be very interesting to most users and is quite extra verbose, so it could be hidden behind a flag.

@tbaederr tbaederr removed the clang:bytecode Issues for the clang bytecode constexpr interpreter label Sep 17, 2025
@cor3ntin
Copy link
Contributor

This seems large enough that it might warrant an RFC with a more detailed motivation

https://clang.llvm.org/get_involved.html#:~:text=The%20Clang%20community%20uses,will%20proceed%20or%20not.

@erichkeane @rnk

@rnk
Copy link
Collaborator

rnk commented Sep 18, 2025

This seems large enough that it might warrant an RFC with a more detailed motivation

https://clang.llvm.org/get_involved.html#:~:text=The%20Clang%20community%20uses,will%20proceed%20or%20not.

@erichkeane @rnk

I think I agree with Aaron's feedback back in August, all those points seem valid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:RISC-V clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category HLSL HLSL Language Support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants