Why isn't CXXDeleteExpr present in the AST when using the nothrow version?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Why isn't CXXDeleteExpr present in the AST when using the nothrow version?

Fangrui Song via cfe-dev
Hi!

I noticed that for using "regular" operator delete, the CXXDeleteExpr is present, and so is CXXNewExpr, but when using the nothrow version, and it is causing me a headache while trying to implement a deallocator event in the clang static analyzer. I have the following declaratations:

namespace std {
typedef __typeof__(sizeof(int)) size_t;
struct nothrow_t {};
extern const nothrow_t nothrow;
} // namespace std

void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();

void* operator new (std::size_t size, void* ptr) throw() { return ptr; };
void* operator new[] (std::size_t size, void* ptr) throw() { return ptr; };
void operator delete (void* ptr, void*) throw() {};
void operator delete[] (void* ptr, void*) throw() {};


In the first code example, the "regular", non-nothrow version is used:

namespace fundamental {
void f() {
  int *p = new int;
  delete p;
}
} // namespace fundamental

namespace fundamental_array {
void f() {
  int *p = new int[2];
  delete[] p;
}
} // namespace fundamental_array


|-NamespaceDecl 0x1e568e0 </home/szelethus/Documents/llvm-project/clang/test/Analysis/operator-delete-analysis-order.cpp:14:1, line:19:1> line:14:11 fundamental
| `-FunctionDecl 0x1e56970 <line:15:1, line:18:1> line:15:6 f 'void ()'
|   `-CompoundStmt 0x1e56b50 <col:10, line:18:1>
|     |-DeclStmt 0x1e56ae0 <line:16:3, col:19>
|     | `-VarDecl 0x1e56a28 <col:3, col:16> col:8 used p 'int *' cinit
|     |   `-CXXNewExpr 0x1e56aa8 <col:12, col:16> 'int *' Function 0x1e25a20 'operator new' 'void *(unsigned long)'
|     `-CXXDeleteExpr 0x1e56b30 <line:17:3, col:10> 'void' Function 0x1e25e00 'operator delete' 'void (void *) noexcept'
|       `-ImplicitCastExpr 0x1e56b18 <col:10> 'int *' <LValueToRValue>
|         `-DeclRefExpr 0x1e56af8 <col:10> 'int *' lvalue Var 0x1e56a28 'p' 'int *'
|-NamespaceDecl 0x1e56b70 <line:21:1, line:26:1> line:21:11 fundamental_array
| `-FunctionDecl 0x1e56c00 <line:22:1, line:25:1> line:22:6 f 'void ()'
|   `-CompoundStmt 0x1e56e58 <col:10, line:25:1>
|     |-DeclStmt 0x1e56de8 <line:23:3, col:22>
|     | `-VarDecl 0x1e56cb8 <col:3, col:21> col:8 used p 'int *' cinit
|     |   `-CXXNewExpr 0x1e56da8 <col:12, col:21> 'int *' array Function 0x1e25be0 'operator new[]' 'void *(unsigned long)'
|     |     `-ImplicitCastExpr 0x1e56d58 <col:20> 'unsigned long' <IntegralCast>
|     |       `-IntegerLiteral 0x1e56d20 <col:20> 'int' 2
|     `-CXXDeleteExpr 0x1e56e38 <line:24:3, col:12> 'void' array Function 0x1e25f68 'operator delete[]' 'void (void *) noexcept'
|       `-ImplicitCastExpr 0x1e56e20 <col:12> 'int *' <LValueToRValue>
|         `-DeclRefExpr 0x1e56e00 <col:12> 'int *' lvalue Var 0x1e56cb8 'p' 'int *'

In the second, the nothrow version. Observe how CXXNewExpr is still present, but not CXXDeleteExpr.

namespace fundamental_nothrow {
void f() {
  int *s = new (std::nothrow) int;
  operator delete(s, std::nothrow);
}
} // namespace nontrivial_destructor

namespace fundamental_array_nothrow {
void f() {
  int *s = new (std::nothrow) int;
  operator delete(s, std::nothrow);
}
} // namespace nontrivial_destructor


|-NamespaceDecl 0x1e59b88 <line:54:1, line:60:1> line:54:11 fundamental_nothrow
| `-FunctionDecl 0x1e59c18 <line:56:1, line:59:1> line:56:6 f 'void ()'
|   `-CompoundStmt 0x1e5a020 <col:10, line:59:1>
|     |-DeclStmt 0x1e59e48 <line:57:3, col:34>
|     | `-VarDecl 0x1e59cd0 <col:3, col:31> col:8 used s 'int *' cinit
|     |   `-CXXNewExpr 0x1e59e08 <col:12, col:31> 'int *' Function 0x1e49a08 'operator new' 'void *(std::size_t, const std::nothrow_t &) throw()'
|     |     `-DeclRefExpr 0x1e59d88 <col:17, col:22> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
|     `-CallExpr 0x1e59fc0 <line:58:3, col:34> 'void'
|       |-ImplicitCastExpr 0x1e59fa8 <col:3, col:12> 'void (*)(void *, const std::nothrow_t &) throw()' <FunctionToPointerDecay>
|       | `-DeclRefExpr 0x1e59f28 <col:3, col:12> 'void (void *, const std::nothrow_t &) throw()' lvalue Function 0x1e49fe0 'operator delete' 'void (void *, const std::nothrow_t &) throw()'
|       |-ImplicitCastExpr 0x1e5a008 <col:19> 'void *' <BitCast>
|       | `-ImplicitCastExpr 0x1e59ff0 <col:19> 'int *' <LValueToRValue>
|       |   `-DeclRefExpr 0x1e59eb8 <col:19> 'int *' lvalue Var 0x1e59cd0 's' 'int *'
|       `-DeclRefExpr 0x1e59ef8 <col:22, col:27> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
`-NamespaceDecl 0x1e5a040 <line:62:1, line:68:1> line:62:11 fundamental_array_nothrow
  `-FunctionDecl 0x1e5a0d0 <line:64:1, line:67:1> line:64:6 f 'void ()'
    `-CompoundStmt 0x1e5a440 <col:10, line:67:1>
      |-DeclStmt 0x1e5a2c8 <line:65:3, col:34>
      | `-VarDecl 0x1e5a188 <col:3, col:31> col:8 used s 'int *' cinit
      |   `-CXXNewExpr 0x1e5a288 <col:12, col:31> 'int *' Function 0x1e49a08 'operator new' 'void *(std::size_t, const std::nothrow_t &) throw()'
      |     `-DeclRefExpr 0x1e5a240 <col:17, col:22> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
      `-CallExpr 0x1e5a3e0 <line:66:3, col:34> 'void'
        |-ImplicitCastExpr 0x1e5a3c8 <col:3, col:12> 'void (*)(void *, const std::nothrow_t &) throw()' <FunctionToPointerDecay>
        | `-DeclRefExpr 0x1e5a3a8 <col:3, col:12> 'void (void *, const std::nothrow_t &) throw()' lvalue Function 0x1e49fe0 'operator delete' 'void (void *, const std::nothrow_t &) throw()'
        |-ImplicitCastExpr 0x1e5a428 <col:19> 'void *' <BitCast>
        | `-ImplicitCastExpr 0x1e5a410 <col:19> 'int *' <LValueToRValue>
        |   `-DeclRefExpr 0x1e5a338 <col:19> 'int *' lvalue Var 0x1e5a188 's' 'int *'
        `-DeclRefExpr 0x1e5a378 <col:22, col:27> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'

Is this intended? If so, why?

Cheers,
Husi

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Why isn't CXXDeleteExpr present in the AST when using the nothrow version?

Fangrui Song via cfe-dev
Strictly speaking, a delete expression's syntax is the following:
::(optional)    delete    expression
::(optional)    delete [] expression
So, in the second case `fundamental_nothrow`, you do not have any delete expression in the AST, because the code syntactically does not contain any. Instead what you do is that you explicitly call a function, that happens to be the `operator delete` function, so you actually have a call expression rather than a delete expression.

Hope this helps,
Gabor

On Thu, Apr 2, 2020 at 4:43 PM Kristóf Umann <[hidden email]> wrote:
Hi!

I noticed that for using "regular" operator delete, the CXXDeleteExpr is present, and so is CXXNewExpr, but when using the nothrow version, and it is causing me a headache while trying to implement a deallocator event in the clang static analyzer. I have the following declaratations:

namespace std {
typedef __typeof__(sizeof(int)) size_t;
struct nothrow_t {};
extern const nothrow_t nothrow;
} // namespace std

void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();

void* operator new (std::size_t size, void* ptr) throw() { return ptr; };
void* operator new[] (std::size_t size, void* ptr) throw() { return ptr; };
void operator delete (void* ptr, void*) throw() {};
void operator delete[] (void* ptr, void*) throw() {};


In the first code example, the "regular", non-nothrow version is used:

namespace fundamental {
void f() {
  int *p = new int;
  delete p;
}
} // namespace fundamental

namespace fundamental_array {
void f() {
  int *p = new int[2];
  delete[] p;
}
} // namespace fundamental_array


|-NamespaceDecl 0x1e568e0 </home/szelethus/Documents/llvm-project/clang/test/Analysis/operator-delete-analysis-order.cpp:14:1, line:19:1> line:14:11 fundamental
| `-FunctionDecl 0x1e56970 <line:15:1, line:18:1> line:15:6 f 'void ()'
|   `-CompoundStmt 0x1e56b50 <col:10, line:18:1>
|     |-DeclStmt 0x1e56ae0 <line:16:3, col:19>
|     | `-VarDecl 0x1e56a28 <col:3, col:16> col:8 used p 'int *' cinit
|     |   `-CXXNewExpr 0x1e56aa8 <col:12, col:16> 'int *' Function 0x1e25a20 'operator new' 'void *(unsigned long)'
|     `-CXXDeleteExpr 0x1e56b30 <line:17:3, col:10> 'void' Function 0x1e25e00 'operator delete' 'void (void *) noexcept'
|       `-ImplicitCastExpr 0x1e56b18 <col:10> 'int *' <LValueToRValue>
|         `-DeclRefExpr 0x1e56af8 <col:10> 'int *' lvalue Var 0x1e56a28 'p' 'int *'
|-NamespaceDecl 0x1e56b70 <line:21:1, line:26:1> line:21:11 fundamental_array
| `-FunctionDecl 0x1e56c00 <line:22:1, line:25:1> line:22:6 f 'void ()'
|   `-CompoundStmt 0x1e56e58 <col:10, line:25:1>
|     |-DeclStmt 0x1e56de8 <line:23:3, col:22>
|     | `-VarDecl 0x1e56cb8 <col:3, col:21> col:8 used p 'int *' cinit
|     |   `-CXXNewExpr 0x1e56da8 <col:12, col:21> 'int *' array Function 0x1e25be0 'operator new[]' 'void *(unsigned long)'
|     |     `-ImplicitCastExpr 0x1e56d58 <col:20> 'unsigned long' <IntegralCast>
|     |       `-IntegerLiteral 0x1e56d20 <col:20> 'int' 2
|     `-CXXDeleteExpr 0x1e56e38 <line:24:3, col:12> 'void' array Function 0x1e25f68 'operator delete[]' 'void (void *) noexcept'
|       `-ImplicitCastExpr 0x1e56e20 <col:12> 'int *' <LValueToRValue>
|         `-DeclRefExpr 0x1e56e00 <col:12> 'int *' lvalue Var 0x1e56cb8 'p' 'int *'

In the second, the nothrow version. Observe how CXXNewExpr is still present, but not CXXDeleteExpr.

namespace fundamental_nothrow {
void f() {
  int *s = new (std::nothrow) int;
  operator delete(s, std::nothrow);
}
} // namespace nontrivial_destructor

namespace fundamental_array_nothrow {
void f() {
  int *s = new (std::nothrow) int;
  operator delete(s, std::nothrow);
}
} // namespace nontrivial_destructor


|-NamespaceDecl 0x1e59b88 <line:54:1, line:60:1> line:54:11 fundamental_nothrow
| `-FunctionDecl 0x1e59c18 <line:56:1, line:59:1> line:56:6 f 'void ()'
|   `-CompoundStmt 0x1e5a020 <col:10, line:59:1>
|     |-DeclStmt 0x1e59e48 <line:57:3, col:34>
|     | `-VarDecl 0x1e59cd0 <col:3, col:31> col:8 used s 'int *' cinit
|     |   `-CXXNewExpr 0x1e59e08 <col:12, col:31> 'int *' Function 0x1e49a08 'operator new' 'void *(std::size_t, const std::nothrow_t &) throw()'
|     |     `-DeclRefExpr 0x1e59d88 <col:17, col:22> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
|     `-CallExpr 0x1e59fc0 <line:58:3, col:34> 'void'
|       |-ImplicitCastExpr 0x1e59fa8 <col:3, col:12> 'void (*)(void *, const std::nothrow_t &) throw()' <FunctionToPointerDecay>
|       | `-DeclRefExpr 0x1e59f28 <col:3, col:12> 'void (void *, const std::nothrow_t &) throw()' lvalue Function 0x1e49fe0 'operator delete' 'void (void *, const std::nothrow_t &) throw()'
|       |-ImplicitCastExpr 0x1e5a008 <col:19> 'void *' <BitCast>
|       | `-ImplicitCastExpr 0x1e59ff0 <col:19> 'int *' <LValueToRValue>
|       |   `-DeclRefExpr 0x1e59eb8 <col:19> 'int *' lvalue Var 0x1e59cd0 's' 'int *'
|       `-DeclRefExpr 0x1e59ef8 <col:22, col:27> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
`-NamespaceDecl 0x1e5a040 <line:62:1, line:68:1> line:62:11 fundamental_array_nothrow
  `-FunctionDecl 0x1e5a0d0 <line:64:1, line:67:1> line:64:6 f 'void ()'
    `-CompoundStmt 0x1e5a440 <col:10, line:67:1>
      |-DeclStmt 0x1e5a2c8 <line:65:3, col:34>
      | `-VarDecl 0x1e5a188 <col:3, col:31> col:8 used s 'int *' cinit
      |   `-CXXNewExpr 0x1e5a288 <col:12, col:31> 'int *' Function 0x1e49a08 'operator new' 'void *(std::size_t, const std::nothrow_t &) throw()'
      |     `-DeclRefExpr 0x1e5a240 <col:17, col:22> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
      `-CallExpr 0x1e5a3e0 <line:66:3, col:34> 'void'
        |-ImplicitCastExpr 0x1e5a3c8 <col:3, col:12> 'void (*)(void *, const std::nothrow_t &) throw()' <FunctionToPointerDecay>
        | `-DeclRefExpr 0x1e5a3a8 <col:3, col:12> 'void (void *, const std::nothrow_t &) throw()' lvalue Function 0x1e49fe0 'operator delete' 'void (void *, const std::nothrow_t &) throw()'
        |-ImplicitCastExpr 0x1e5a428 <col:19> 'void *' <BitCast>
        | `-ImplicitCastExpr 0x1e5a410 <col:19> 'int *' <LValueToRValue>
        |   `-DeclRefExpr 0x1e5a338 <col:19> 'int *' lvalue Var 0x1e5a188 's' 'int *'
        `-DeclRefExpr 0x1e5a378 <col:22, col:27> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'

Is this intended? If so, why?

Cheers,
Husi

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Why isn't CXXDeleteExpr present in the AST when using the nothrow version?

Fangrui Song via cfe-dev
In reply to this post by Fangrui Song via cfe-dev
Hi Chris, 

The reason there is no CXXDeleteExpr is because you aren't using the delete operator.
Unfortunately there is no placement delete operator in c++ to help out with this. 
Your best bet is to match against CallExpr that calls 'operator delete'.

Regards,
Nathan James

On Thu, 2020-04-02 at 16:42 +0200, Kristóf Umann via cfe-dev wrote:
Hi!

I noticed that for using "regular" operator delete, the CXXDeleteExpr is present, and so is CXXNewExpr, but when using the nothrow version, and it is causing me a headache while trying to implement a deallocator event in the clang static analyzer. I have the following declaratations:

namespace std {
typedef __typeof__(sizeof(int)) size_t;
struct nothrow_t {};
extern const nothrow_t nothrow;
} // namespace std

void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();

void* operator new (std::size_t size, void* ptr) throw() { return ptr; };
void* operator new[] (std::size_t size, void* ptr) throw() { return ptr; };
void operator delete (void* ptr, void*) throw() {};
void operator delete[] (void* ptr, void*) throw() {};


In the first code example, the "regular", non-nothrow version is used:

namespace fundamental {
void f() {
  int *p = new int;
  delete p;
}
} // namespace fundamental

namespace fundamental_array {
void f() {
  int *p = new int[2];
  delete[] p;
}
} // namespace fundamental_array


|-NamespaceDecl 0x1e568e0 </home/szelethus/Documents/llvm-project/clang/test/Analysis/operator-delete-analysis-order.cpp:14:1, line:19:1> line:14:11 fundamental
| `-FunctionDecl 0x1e56970 <line:15:1, line:18:1> line:15:6 f 'void ()'
|   `-CompoundStmt 0x1e56b50 <col:10, line:18:1>
|     |-DeclStmt 0x1e56ae0 <line:16:3, col:19>
|     | `-VarDecl 0x1e56a28 <col:3, col:16> col:8 used p 'int *' cinit
|     |   `-CXXNewExpr 0x1e56aa8 <col:12, col:16> 'int *' Function 0x1e25a20 'operator new' 'void *(unsigned long)'
|     `-CXXDeleteExpr 0x1e56b30 <line:17:3, col:10> 'void' Function 0x1e25e00 'operator delete' 'void (void *) noexcept'
|       `-ImplicitCastExpr 0x1e56b18 <col:10> 'int *' <LValueToRValue>
|         `-DeclRefExpr 0x1e56af8 <col:10> 'int *' lvalue Var 0x1e56a28 'p' 'int *'
|-NamespaceDecl 0x1e56b70 <line:21:1, line:26:1> line:21:11 fundamental_array
| `-FunctionDecl 0x1e56c00 <line:22:1, line:25:1> line:22:6 f 'void ()'
|   `-CompoundStmt 0x1e56e58 <col:10, line:25:1>
|     |-DeclStmt 0x1e56de8 <line:23:3, col:22>
|     | `-VarDecl 0x1e56cb8 <col:3, col:21> col:8 used p 'int *' cinit
|     |   `-CXXNewExpr 0x1e56da8 <col:12, col:21> 'int *' array Function 0x1e25be0 'operator new[]' 'void *(unsigned long)'
|     |     `-ImplicitCastExpr 0x1e56d58 <col:20> 'unsigned long' <IntegralCast>
|     |       `-IntegerLiteral 0x1e56d20 <col:20> 'int' 2
|     `-CXXDeleteExpr 0x1e56e38 <line:24:3, col:12> 'void' array Function 0x1e25f68 'operator delete[]' 'void (void *) noexcept'
|       `-ImplicitCastExpr 0x1e56e20 <col:12> 'int *' <LValueToRValue>
|         `-DeclRefExpr 0x1e56e00 <col:12> 'int *' lvalue Var 0x1e56cb8 'p' 'int *'

In the second, the nothrow version. Observe how CXXNewExpr is still present, but not CXXDeleteExpr.

namespace fundamental_nothrow {
void f() {
  int *s = new (std::nothrow) int;
  operator delete(s, std::nothrow);
}
} // namespace nontrivial_destructor

namespace fundamental_array_nothrow {
void f() {
  int *s = new (std::nothrow) int;
  operator delete(s, std::nothrow);
}
} // namespace nontrivial_destructor


|-NamespaceDecl 0x1e59b88 <line:54:1, line:60:1> line:54:11 fundamental_nothrow
| `-FunctionDecl 0x1e59c18 <line:56:1, line:59:1> line:56:6 f 'void ()'
|   `-CompoundStmt 0x1e5a020 <col:10, line:59:1>
|     |-DeclStmt 0x1e59e48 <line:57:3, col:34>
|     | `-VarDecl 0x1e59cd0 <col:3, col:31> col:8 used s 'int *' cinit
|     |   `-CXXNewExpr 0x1e59e08 <col:12, col:31> 'int *' Function 0x1e49a08 'operator new' 'void *(std::size_t, const std::nothrow_t &) throw()'
|     |     `-DeclRefExpr 0x1e59d88 <col:17, col:22> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
|     `-CallExpr 0x1e59fc0 <line:58:3, col:34> 'void'
|       |-ImplicitCastExpr 0x1e59fa8 <col:3, col:12> 'void (*)(void *, const std::nothrow_t &) throw()' <FunctionToPointerDecay>
|       | `-DeclRefExpr 0x1e59f28 <col:3, col:12> 'void (void *, const std::nothrow_t &) throw()' lvalue Function 0x1e49fe0 'operator delete' 'void (void *, const std::nothrow_t &) throw()'
|       |-ImplicitCastExpr 0x1e5a008 <col:19> 'void *' <BitCast>
|       | `-ImplicitCastExpr 0x1e59ff0 <col:19> 'int *' <LValueToRValue>
|       |   `-DeclRefExpr 0x1e59eb8 <col:19> 'int *' lvalue Var 0x1e59cd0 's' 'int *'
|       `-DeclRefExpr 0x1e59ef8 <col:22, col:27> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
`-NamespaceDecl 0x1e5a040 <line:62:1, line:68:1> line:62:11 fundamental_array_nothrow
  `-FunctionDecl 0x1e5a0d0 <line:64:1, line:67:1> line:64:6 f 'void ()'
    `-CompoundStmt 0x1e5a440 <col:10, line:67:1>
      |-DeclStmt 0x1e5a2c8 <line:65:3, col:34>
      | `-VarDecl 0x1e5a188 <col:3, col:31> col:8 used s 'int *' cinit
      |   `-CXXNewExpr 0x1e5a288 <col:12, col:31> 'int *' Function 0x1e49a08 'operator new' 'void *(std::size_t, const std::nothrow_t &) throw()'
      |     `-DeclRefExpr 0x1e5a240 <col:17, col:22> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'
      `-CallExpr 0x1e5a3e0 <line:66:3, col:34> 'void'
        |-ImplicitCastExpr 0x1e5a3c8 <col:3, col:12> 'void (*)(void *, const std::nothrow_t &) throw()' <FunctionToPointerDecay>
        | `-DeclRefExpr 0x1e5a3a8 <col:3, col:12> 'void (void *, const std::nothrow_t &) throw()' lvalue Function 0x1e49fe0 'operator delete' 'void (void *, const std::nothrow_t &) throw()'
        |-ImplicitCastExpr 0x1e5a428 <col:19> 'void *' <BitCast>
        | `-ImplicitCastExpr 0x1e5a410 <col:19> 'int *' <LValueToRValue>
        |   `-DeclRefExpr 0x1e5a338 <col:19> 'int *' lvalue Var 0x1e5a188 's' 'int *'
        `-DeclRefExpr 0x1e5a378 <col:22, col:27> 'const std::nothrow_t' lvalue Var 0x1e26360 'nothrow' 'const std::nothrow_t'

Is this intended? If so, why?

Cheers,
Husi
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev