Skip to content

[Clang][Sema] Correctly transform dependent operands of overloaded binary operator& #97596

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 2 commits into from
Jul 3, 2024

Conversation

sdkrystian
Copy link
Member

Currently, TreeTransform::TransformCXXOperatorCallExpr calls TreeTransform::TransformAddressOfOperand to transform the first operand of a CXXOperatorCallExpr when its OverloadOperatorKind is OO_Amp -- regardless of arity. This results in the first operand of binary operator& being incorrectly transformed as if it was the operand of the address of operator in cases such as the following:

struct A {
  int x;
};

void operator&(A, A);

template<typename T>
struct B {
  int f() {
    return T::x & 1; // invalid reference to 'A::x' is not diagnosed because 'T::x' is incorrectly transformed as if it was the operand of unary operator&
  }
};

template struct B<A>;

Prior to #92318 we would build a CXXDependentScopeMemberExpr for T::x (as with most dependent qualified names that were not member qualified names). Since TreeTransform::TransformAddressOfOperand only differs from TransformExpr for DependentScopeDeclRefExpr and UnresolvedLookupExpr operands, T::x was transformed "correctly". Now that we build a DependentScopeDeclRefExpr for T::x, it is incorrectly transformed as if it was the operand of the address of operator and we fail to diagnose the invalid reference to a non-static data member. This patch fixes the issue by only calling TreeTransform::TransformAddressOfOperand for CXXOperatorCallExprs with a single operand. This fixes #97483.

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

llvmbot commented Jul 3, 2024

@llvm/pr-subscribers-clang

Author: Krystian Stasiowski (sdkrystian)

Changes

Currently, TreeTransform::TransformCXXOperatorCallExpr calls TreeTransform::TransformAddressOfOperand to transform the first operand of a CXXOperatorCallExpr when its OverloadOperatorKind is OO_Amp -- regardless of arity. This results in the first operand of binary operator&amp; being incorrectly transformed as if it was the operand of the address of operator in cases such as the following:

struct A {
  int x;
};

void operator&amp;(A, A);

template&lt;typename T&gt;
struct B {
  int f() {
    return T::x &amp; 1; // invalid reference to 'A::x' is not diagnosed because 'T::x' is incorrectly transformed as if it was the operand of unary operator&amp;
  }
};

template struct B&lt;A&gt;;

Prior to #92318 we would build a CXXDependentScopeMemberExpr for T::x (as with most dependent qualified names that were not member qualified names). Since TreeTransform::TransformAddressOfOperand only differs from TransformExpr for DependentScopeDeclRefExpr and UnresolvedLookupExpr operands, T::x was transformed "correctly". Now that we build a DependentScopeDeclRefExpr for T::x, it is incorrectly transformed as if it was the operand of the address of operator and we fail to diagnose the invalid reference to a non-static data member. This patch fixes the issue by only calling TreeTransform::TransformAddressOfOperand for CXXOperatorCallExprs with a single operand. This fixes #97483.


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

2 Files Affected:

  • (modified) clang/lib/Sema/TreeTransform.h (+1-1)
  • (added) clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.general/p4.cpp (+16)
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 51ba22f99e3a3..4450ebaf615cd 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -12919,7 +12919,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
   }
 
   ExprResult First;
-  if (E->getOperator() == OO_Amp)
+  if (E->getNumArgs() == 1 && E->getOperator() == OO_Amp)
     First = getDerived().TransformAddressOfOperand(E->getArg(0));
   else
     First = getDerived().TransformExpr(E->getArg(0));
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.general/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.general/p4.cpp
new file mode 100644
index 0000000000000..e6d9c171e3893
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.general/p4.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -verify %s
+
+struct A {
+  int x;
+};
+
+void operator&(A, A);
+
+template<typename T>
+struct B {
+  int f() {
+    return T::x & 1; // expected-error {{invalid use of non-static data member 'x'}}
+  }
+};
+
+template struct B<A>; // expected-note {{in instantiation of}}

@sdkrystian sdkrystian merged commit 10b43f4 into llvm:main Jul 3, 2024
8 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 3, 2024

LLVM Buildbot has detected a new failure on builder arc-builder running on arc-worker while building clang at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/3/builds/1033

Here is the relevant piece of the build log for the reference:

Step 6 (test-build-unified-tree-check-all) failure: 1200 seconds without output running [b'ninja', b'check-all'], attempting to kill
...

OK
10.117 [33/18/25] Linking CXX executable unittests/DebugInfo/Symbolizer/DebugInfoSymbolizerTests
10.137 [32/18/26] Linking CXX executable unittests/DebugInfo/GSYM/DebugInfoGSYMTests
10.559 [31/18/27] Linking CXX executable unittests/DWARFLinkerParallel/DWARFLinkerParallelTests
10.795 [30/18/28] Linking CXX executable unittests/DebugInfo/PDB/DebugInfoPDBTests
10.864 [29/18/29] Linking CXX executable unittests/Debuginfod/DebuginfodTests
11.286 [28/18/30] Linking CXX executable unittests/ExecutionEngine/ExecutionEngineTests
11.293 [27/18/31] Linking CXX executable unittests/DebugInfo/LogicalView/DebugInfoLogicalViewTests
11.740 [26/18/32] Linking CXX executable unittests/ExecutionEngine/JITLink/JITLinkTests
command timed out: 1200 seconds without output running [b'ninja', b'check-all'], attempting to kill
process killed by signal 9
program finished with exit code -1
elapsedTime=1212.434721

kbluck pushed a commit to kbluck/llvm-project that referenced this pull request Jul 6, 2024
…nary operator& (llvm#97596)

Currently, `TreeTransform::TransformCXXOperatorCallExpr` calls
`TreeTransform::TransformAddressOfOperand` to transform the first
operand of a `CXXOperatorCallExpr` when its `OverloadOperatorKind` is
`OO_Amp` -- regardless of arity. This results in the first operand of
binary `operator&` being incorrectly transformed as if it was the
operand of the address of operator in cases such as the following:
```
struct A {
  int x;
};

void operator&(A, A);

template<typename T>
struct B {
  int f() {
    return T::x & 1; // invalid reference to 'A::x' is not diagnosed because 'T::x' is incorrectly transformed as if it was the operand of unary operator&
  }
};

template struct B<A>;
```
Prior to llvm#92318 we would build a `CXXDependentScopeMemberExpr` for
`T::x` (as with most dependent qualified names that were not member
qualified names). Since `TreeTransform::TransformAddressOfOperand` only
differs from `TransformExpr` for `DependentScopeDeclRefExpr` and
`UnresolvedLookupExpr` operands, `T::x` was transformed "correctly". Now
that we build a `DependentScopeDeclRefExpr` for `T::x`, it is
incorrectly transformed as if it was the operand of the address of
operator and we fail to diagnose the invalid reference to a non-static
data member. This patch fixes the issue by only calling
`TreeTransform::TransformAddressOfOperand` for `CXXOperatorCallExpr`s
with a single operand. This fixes llvm#97483.
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.

[clang] Crash in clang codegen after CXXDependentScopeMemberExpr change
4 participants