Skip to content

Commit

Permalink
[Clang] Properly set the value category of dependent unary operators (#…
Browse files Browse the repository at this point in the history
…88740)

This fixes an assertion in Expr::Classify when a
trying to deduce a dependent dereference operator.

Fixes #88329
  • Loading branch information
cor3ntin committed Apr 15, 2024
1 parent 43b4e5b commit b03dc7d
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 5 deletions.
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Expand Up @@ -537,6 +537,7 @@ Bug Fixes to C++ Support
- Clang now correctly tracks type dependence of by-value captures in lambdas with an explicit
object parameter.
Fixes (#GH70604), (#GH79754), (#GH84163), (#GH84425), (#GH86054), (#GH86398), and (#GH86399).
- Fix a crash when deducing ``auto`` from an invalid dereference (#GH88329).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
13 changes: 10 additions & 3 deletions clang/lib/Sema/SemaOverload.cpp
Expand Up @@ -14395,9 +14395,16 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
ArrayRef<Expr *> ArgsArray(Args, NumArgs);

if (Input->isTypeDependent()) {
ExprValueKind VK = ExprValueKind::VK_PRValue;
// [C++26][expr.unary.op][expr.pre.incr]
// The * operator yields an lvalue of type
// The pre/post increment operators yied an lvalue.
if (Opc == UO_PreDec || Opc == UO_PreInc || Opc == UO_Deref)
VK = VK_LValue;

if (Fns.empty())
return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
VK_PRValue, OK_Ordinary, OpLoc, false,
return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy, VK,
OK_Ordinary, OpLoc, false,
CurFPFeatureOverrides());

CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
Expand All @@ -14406,7 +14413,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray,
Context.DependentTy, VK_PRValue, OpLoc,
Context.DependentTy, VK, OpLoc,
CurFPFeatureOverrides());
}

Expand Down
4 changes: 2 additions & 2 deletions clang/test/CXX/over/over.built/ast.cpp
Expand Up @@ -4,11 +4,11 @@ struct A{};

template <typename T, typename U>
auto Test(T* pt, U* pu) {
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '*'
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '*'
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
(void)*pt;

// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '++'
// CHECK: UnaryOperator {{.*}} '<dependent type>' lvalue prefix '++'
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
(void)(++pt);

Expand Down
10 changes: 10 additions & 0 deletions clang/test/SemaCXX/overloaded-operator.cpp
Expand Up @@ -682,3 +682,13 @@ namespace nw{
}
}
#endif

#if __cplusplus >= 201703L
namespace GH88329 {

template <auto T> struct A {};
template <auto T> A<*T> operator *() { return {}; }
// expected-error@-1 {{overloaded 'operator*' must have at least one parameter of class or enumeration type}}
}

#endif

0 comments on commit b03dc7d

Please sign in to comment.