diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -573,6 +573,9 @@ - Stop evaluating a constant expression if the condition expression which in switch statement contains errors. (`#63453 _`) +- Fixed false positive error diagnostic when pack expansion appears in template + parameters of a member expression. + (`#48731 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -611,9 +611,24 @@ 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(MemberDecl)) { DeclContext *DC = MemberDecl->getDeclContext(); // dyn_cast_or_null is used to handle objC variables which do not @@ -723,15 +738,6 @@ 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, diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1759,16 +1759,7 @@ 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 = @@ -1780,13 +1771,16 @@ 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()->initializeFrom( TemplateKWLoc, *TemplateArgs, E->getTrailingObjects(), 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()->initializeFrom( TemplateKWLoc); diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp @@ -306,3 +306,22 @@ f(A()); // OK } } + +namespace GH48731 { +template using N = int; +struct X { template void f(); }; +template decltype((X().f>(), ...)) x; +template decltype(((new X())->f>(), ...)) y; + +struct A {}; +template using Tfoo = A; +template void foo(A a) { + (a.~Tfoo(), ...); +} + +struct B { operator int(); }; +template using Tbar = int; +template void bar(B b) { + (b.operator Tbar(), ...); +} +}