-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[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
Conversation
@llvm/pr-subscribers-clang Author: Krystian Stasiowski (sdkrystian) ChangesCurrently, 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 Full diff: https://github.com/llvm/llvm-project/pull/97596.diff 2 Files Affected:
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}}
|
LLVM Buildbot has detected a new failure on builder 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:
|
…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.
Currently,
TreeTransform::TransformCXXOperatorCallExpr
callsTreeTransform::TransformAddressOfOperand
to transform the first operand of aCXXOperatorCallExpr
when itsOverloadOperatorKind
isOO_Amp
-- regardless of arity. This results in the first operand of binaryoperator&
being incorrectly transformed as if it was the operand of the address of operator in cases such as the following:Prior to #92318 we would build a
CXXDependentScopeMemberExpr
forT::x
(as with most dependent qualified names that were not member qualified names). SinceTreeTransform::TransformAddressOfOperand
only differs fromTransformExpr
forDependentScopeDeclRefExpr
andUnresolvedLookupExpr
operands,T::x
was transformed "correctly". Now that we build aDependentScopeDeclRefExpr
forT::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 callingTreeTransform::TransformAddressOfOperand
forCXXOperatorCallExpr
s with a single operand. This fixes #97483.