Skip to content

Commit

Permalink
[clang] Correct calculation of MemberExpr's dependence
Browse files Browse the repository at this point in the history
Due to incorrect calculation false positive diagnostics were emitted.

Fixes #48731

Reviewed By: shafik, cor3ntin

Differential Revision: https://reviews.llvm.org/D154689
  • Loading branch information
Fznamznon committed Jul 10, 2023
1 parent f250fbc commit a0130fc
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 21 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,9 @@ Bug Fixes in This Version
- Stop evaluating a constant expression if the condition expression which in
switch statement contains errors.
(`#63453 <https://github.com/llvm/llvm-project/issues/63453>_`)
- Fixed false positive error diagnostic when pack expansion appears in template
parameters of a member expression.
(`#48731 <https://github.com/llvm/llvm-project/issues/48731>`_)

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
26 changes: 16 additions & 10 deletions clang/lib/AST/ComputeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,9 +611,24 @@ ExprDependence clang::computeDependence(OffsetOfExpr *E) {
return D;
}

static inline ExprDependence getDependenceInExpr(DeclarationNameInfo Name) {
auto D = ExprDependence::None;
if (Name.isInstantiationDependent())
D |= ExprDependence::Instantiation;
if (Name.containsUnexpandedParameterPack())
D |= ExprDependence::UnexpandedPack;
return D;
}

ExprDependence clang::computeDependence(MemberExpr *E) {
auto *MemberDecl = E->getMemberDecl();
auto D = E->getBase()->getDependence();
D |= getDependenceInExpr(E->getMemberNameInfo());

if (auto *NNS = E->getQualifier())
D |= toExprDependence(NNS->getDependence() &
~NestedNameSpecifierDependence::Dependent);

auto *MemberDecl = E->getMemberDecl();
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) {
DeclContext *DC = MemberDecl->getDeclContext();
// dyn_cast_or_null is used to handle objC variables which do not
Expand Down Expand Up @@ -723,15 +738,6 @@ ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) {
return D;
}

static inline ExprDependence getDependenceInExpr(DeclarationNameInfo Name) {
auto D = ExprDependence::None;
if (Name.isInstantiationDependent())
D |= ExprDependence::Instantiation;
if (Name.containsUnexpandedParameterPack())
D |= ExprDependence::UnexpandedPack;
return D;
}

ExprDependence
clang::computeDependence(OverloadExpr *E, bool KnownDependent,
bool KnownInstantiationDependent,
Expand Down
16 changes: 5 additions & 11 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1759,16 +1759,7 @@ MemberExpr *MemberExpr::Create(
MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,
NameInfo, T, VK, OK, NOUR);

// FIXME: remove remaining dependence computation to computeDependence().
auto Deps = E->getDependence();
if (HasQualOrFound) {
// FIXME: Wrong. We should be looking at the member declaration we found.
if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent())
Deps |= ExprDependence::TypeValueInstantiation;
else if (QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent())
Deps |= ExprDependence::Instantiation;

E->MemberExprBits.HasQualifierOrFoundDecl = true;

MemberExprNameQualifier *NQ =
Expand All @@ -1780,13 +1771,16 @@ MemberExpr *MemberExpr::Create(
E->MemberExprBits.HasTemplateKWAndArgsInfo =
TemplateArgs || TemplateKWLoc.isValid();

// FIXME: remove remaining dependence computation to computeDependence().
auto Deps = E->getDependence();
if (TemplateArgs) {
auto TemplateArgDeps = TemplateArgumentDependence::None;
E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc, *TemplateArgs,
E->getTrailingObjects<TemplateArgumentLoc>(), TemplateArgDeps);
if (TemplateArgDeps & TemplateArgumentDependence::Instantiation)
Deps |= ExprDependence::Instantiation;
for (const TemplateArgumentLoc &ArgLoc : TemplateArgs->arguments()) {
Deps |= toExprDependence(ArgLoc.getArgument().getDependence());
}
} else if (TemplateKWLoc.isValid()) {
E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
TemplateKWLoc);
Expand Down
19 changes: 19 additions & 0 deletions clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,22 @@ namespace DependentCTAD {
f<B>(A<B(0)>()); // OK
}
}

namespace GH48731 {
template <int> using N = int;
struct X { template<typename T> void f(); };
template<int ...Is> decltype((X().f<N<Is>>(), ...)) x;
template<int ...Is> decltype(((new X())->f<N<Is>>(), ...)) y;

struct A {};
template<int> using Tfoo = A;
template<int ...Ns> void foo(A a) {
(a.~Tfoo<Ns>(), ...);
}

struct B { operator int(); };
template<int> using Tbar = int;
template<int ...Ns> void bar(B b) {
(b.operator Tbar<Ns>(), ...);
}
}

0 comments on commit a0130fc

Please sign in to comment.