Skip to content

[clang][ast]: Add DynamicAllocLValue and TypeInfoLValue support to APValue::dump(). #135178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 15, 2025

Conversation

YLChenZ
Copy link
Contributor

@YLChenZ YLChenZ commented Apr 10, 2025

Closes #134996.
The crash about TypeInfoLValue is https://godbolt.org/z/73WY31s55.
After the patch:

//test.cpp
#include <typeinfo>
constexpr const std::type_info* val = &typeid(int);
lambda@ubuntu22:~/test$ clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only test.cpp
LValue Base=TypeInfoLValue typeid(int), Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
//DAtest.cpp
constexpr int *m = new int(42);
lambda@ubuntu22:~/test$ clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only DAtest.cpp
LValue Base=DynamicAllocLValue 'int', Null=0, Offset=0, HasPath=1, PathLength=0, Path=()

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Apr 10, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 10, 2025

@llvm/pr-subscribers-clang

Author: None (YLChenZ)

Changes

Closes #134996.

The crash about TypeInfoLValue is https://godbolt.org/z/73WY31s55. The crash about DynamicAllocLValue I don't know how to reproduce it yet.

Before the patch:

......
`-VarDecl 0x118857f0 &lt;&lt;source&gt;:3:1, col:50&gt; col:33 val 'const std::type_info *const' constexpr cinit
  |-value: LValue Base=
clang++: /root/llvm-project/llvm/include/llvm/Support/Casting.h:566: decltype(auto) llvm::cast(const From&amp;) [with To = const clang::ValueDecl*; From = llvm::PointerUnion&lt;const clang::ValueDecl*, const clang::Expr*, clang::TypeInfoLValue, clang::DynamicAllocLValue&gt;]: Assertion `isa&lt;To&gt;(Val) &amp;&amp; "cast&lt;Ty&gt;() argument of incompatible type!"' failed.

After the patch:

......
`-VarDecl 0x55b81259b750 &lt;test.cpp:3:1, col:50&gt; col:33 val 'const std::type_info *const' constexpr cinit
  |-value: LValue Base=TypeInfoLValue, Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
  `-UnaryOperator 0x55b81259b7f0 &lt;col:39, col:50&gt; 'const std::type_info *' prefix '&amp;' cannot overflow
    `-CXXTypeidExpr 0x55b81259b7d0 &lt;col:40, col:50&gt; 'const std::type_info' lvalue

Full diff: https://github.com/llvm/llvm-project/pull/135178.diff

2 Files Affected:

  • (modified) clang/lib/AST/TextNodeDumper.cpp (+4)
  • (modified) clang/test/AST/ast-dump-APValue-lvalue.cpp (+10-2)
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index be8d609974d81..0849e5642f006 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -738,6 +738,10 @@ void TextNodeDumper::Visit(const APValue &Value, QualType Ty) {
     else if (const auto *BE = B.dyn_cast<const Expr *>()) {
       OS << BE->getStmtClassName() << ' ';
       dumpPointer(BE);
+    } else if (B.is<TypeInfoLValue>()) {
+      OS << "TypeInfoLValue";
+    } else if (B.is<DynamicAllocLValue>()) {
+      OS << "DynamicAllocLValue";
     } else {
       const auto *VDB = B.get<const ValueDecl *>();
       OS << VDB->getDeclKindName() << "Decl";
diff --git a/clang/test/AST/ast-dump-APValue-lvalue.cpp b/clang/test/AST/ast-dump-APValue-lvalue.cpp
index 224caddb3eabe..7e520254da41a 100644
--- a/clang/test/AST/ast-dump-APValue-lvalue.cpp
+++ b/clang/test/AST/ast-dump-APValue-lvalue.cpp
@@ -23,6 +23,10 @@ struct F {
 };
 F f;
 
+namespace std {
+  class type_info;
+}
+
 void Test(int (&arr)[10]) {
   constexpr int *pi = &i;
   // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pi 'int *const' constexpr cinit
@@ -45,6 +49,10 @@ void Test(int (&arr)[10]) {
   // CHECK-NEXT:  |   |-value: LValue Base=VarDecl {{.*}}, Null=0, Offset=2, HasPath=1, PathLength=2, Path=({{.*}}, 2)
 
   constexpr const int *n = nullptr;
-  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} n 'const int *const' constexpr cinit
-  // CHECK-NEXT:      |-value: LValue Base=null, Null=1, Offset=0, HasPath=1, PathLength=0, Path=()
+  // CHECK:  | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} n 'const int *const' constexpr cinit
+  // CHECK-NEXT:  |   |-value: LValue Base=null, Null=1, Offset=0, HasPath=1, PathLength=0, Path=()
+
+  constexpr const std::type_info* pti = &typeid(int);
+  // CHECK:    `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pti 'const std::type_info *const' constexpr cinit
+  // CHECK-NEXT:      |-value: LValue Base=TypeInfoLValue, Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
 }

Comment on lines 741 to 747
} else if (B.is<TypeInfoLValue>()) {
OS << "TypeInfoLValue";
} else if (B.is<DynamicAllocLValue>()) {
OS << "DynamicAllocLValue";
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be good to print more information about them.

@tbaederr
Copy link
Contributor

tbaederr commented Apr 11, 2025

I don't think we can test DynamicAllocLValue like this, since we can't save it in the APValue for an initialized global. You'll have to add a call to dump() e.g. like:

diff --git i/clang/lib/AST/ExprConstant.cpp w/clang/lib/AST/ExprConstant.cpp
index d1cc722fb794..df52ff82ea2a 100644
--- i/clang/lib/AST/ExprConstant.cpp
+++ w/clang/lib/AST/ExprConstant.cpp
@@ -17087,6 +17087,8 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
         return false;
     }

+    Value.dump();
+
     // At this point, any lifetime-extended temporaries are completely
     // initialized.
     Info.performLifetimeExtension();

then you can compile

constexpr int *m = new int(12);

to reproduce it.

@YLChenZ
Copy link
Contributor Author

YLChenZ commented Apr 11, 2025

I don't think we can test DynamicAllocLValue like this, since we can't save it in the APValue for an initialized global. You'll have to add a call to dump() e.g. like:

diff --git i/clang/lib/AST/ExprConstant.cpp w/clang/lib/AST/ExprConstant.cpp
index d1cc722fb794..df52ff82ea2a 100644
--- i/clang/lib/AST/ExprConstant.cpp
+++ w/clang/lib/AST/ExprConstant.cpp
@@ -17087,6 +17087,8 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
         return false;
     }

+    Value.dump();
+
     // At this point, any lifetime-extended temporaries are completely
     // initialized.
     Info.performLifetimeExtension();

then you can compile

constexpr int *m = new int(12);

to reproduce it.

Okay, I got it. Already reproduced the crash.

lambda@ubuntu22:~/test$ clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only DAtest.cpp
LValue Base=DynamicAllocLValue, Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
DAtest.cpp:1:16: error: constexpr variable 'm' must be initialized by a constant expression
    1 | constexpr int *m = new int(42);
      |                ^   ~~~~~~~~~~~
DAtest.cpp:1:16: note: pointer to heap-allocated object is not a constant expression
DAtest.cpp:1:20: note: heap allocation performed here
    1 | constexpr int *m = new int(42);
      |                    ^
LValue Base=DynamicAllocLValue, Null=0, Offset=0, HasPath=1, PathLength=0, Path=()

@YLChenZ
Copy link
Contributor Author

YLChenZ commented Apr 11, 2025

Would be good to print more information about them.

@tbaederr It seems to only dump their type, like this:

case APValue::LValue: {
    (void)Context;
    OS << "LValue Base=";
    APValue::LValueBase B = Value.getLValueBase();
    ...
    } else if (B.is<TypeInfoLValue>()) {
      OS << "TypeInfoLValue";
      const auto BTI = B.get<TypeInfoLValue>();
      BTI.print(OS, PrintPolicy);
    } else if (B.is<DynamicAllocLValue>()) {
      OS << "DynamicAllocLValue";
      auto BDA = B.getDynamicAllocType();
      dumpType(BDA);
    }
//test.cpp
#include <typeinfo>
constexpr const std::type_info* val = &typeid(int);
lambda@ubuntu22:~/test$ clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only test.cpp
LValue Base=TypeInfoLValue typeid(int), Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
//DAtest.cpp
constexpr int *m = new int(42);
lambda@ubuntu22:~/test$ clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only DAtest.cpp
LValue Base=DynamicAllocLValue 'int', Null=0, Offset=0, HasPath=1, PathLength=0, Path=()

Copy link

github-actions bot commented Apr 14, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@YLChenZ YLChenZ requested a review from tbaederr April 14, 2025 03:42
@tbaederr
Copy link
Contributor

Can you merge this or do you need to someone else to do it for you?

@YLChenZ
Copy link
Contributor Author

YLChenZ commented Apr 15, 2025

@tbaederr I don't have access to merge pr. It should require some help to merge.

@tbaederr tbaederr merged commit 9a6c001 into llvm:main Apr 15, 2025
10 of 11 checks passed
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…Value::dump(). (llvm#135178)

Closes llvm#134996.
The crash about `TypeInfoLValue` is https://godbolt.org/z/73WY31s55. 
After the patch:
```cpp
//test.cpp
#include <typeinfo>
constexpr const std::type_info* val = &typeid(int);
```
```
lambda@ubuntu22:~/test$ clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only test.cpp
LValue Base=TypeInfoLValue typeid(int), Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
```

```cpp
//DAtest.cpp
constexpr int *m = new int(42);
```
```
lambda@ubuntu22:~/test$ clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only DAtest.cpp
LValue Base=DynamicAllocLValue 'int', Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add DynamicAllocLValue and TypeInfoLValue support to APValue::dump()
3 participants