[all-commits] [llvm/llvm-project] fd87d7: [Clang][Sema] Don't build CXXDependentScopeMemberE...

Krystian Stasiowski via All-commits all-commits at lists.llvm.org
Mon May 20 10:55:24 PDT 2024


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: fd87d765c0455265aea4595a3741a96b4c078fbc
      https://github.com/llvm/llvm-project/commit/fd87d765c0455265aea4595a3741a96b4c078fbc
  Author: Krystian Stasiowski <sdkrystian at gmail.com>
  Date:   2024-05-20 (Mon, 20 May 2024)

  Changed paths:
    M clang/docs/ReleaseNotes.rst
    M clang/include/clang/Sema/Sema.h
    M clang/lib/Sema/SemaCXXScopeSpec.cpp
    M clang/lib/Sema/SemaExpr.cpp
    M clang/lib/Sema/SemaLookup.cpp
    M clang/lib/Sema/SemaTemplate.cpp
    M clang/lib/Sema/TreeTransform.h
    M clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp
    M clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp
    M clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp
    M clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

  Log Message:
  -----------
  [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (#92318)

According to [expr.prim.id.general] p2:
> If an _id-expression_ `E` denotes a non-static non-type member of some
class `C` at a point where the current class is `X` and
> - `E` is potentially evaluated or `C` is `X` or a base class of `X`,
and
> - `E` is not the _id-expression_ of a class member access expression,
and
> - if `E` is a _qualified-id_, `E` is not the un-parenthesized operand
of the unary `&` operator,
>
> the _id-expression_ is transformed into a class member access
expression using `(*this)` as the object expression.

Consider the following:
```
struct A
{
    void f0();

    template<typename T>
    void f1();
};

template<typename T>
struct B : T
{
    auto g0() -> decltype(T::f0()); // ok

    auto g1() -> decltype(T::template f1<int>()); // error: call to non-static member function without an object argument
};

template struct B<A>;
```

Clang incorrectly rejects the call to `f1` in the _trailing-return-type_
of `g1`. Furthermore, the following snippet results in a crash during
codegen:
```
struct A
{
    void f();
};

template<typename T>
struct B : T
{
    template<typename U>
    static void g();
    
    template<>
    void g<int>()
    {
        return T::f(); // crash here
    }
};

template struct B<A>;
```
This happens because we unconditionally build a
`CXXDependentScopeMemberExpr` (with an implicit object expression) for
`T::f` when parsing the template definition, even though we don't know
whether `g` is an implicit object member function yet.

This patch fixes these issues by instead building
`DependentScopeDeclRefExpr`s for such expressions, and only transforming
them into implicit class member access expressions during instantiation.
Since we implemented the MS "unqualified lookup into dependent bases"
extension by building an implicit class member access (and relying on
the first component name of the _nested-name-specifier_ to be looked up
in the context of the object expression during instantiation), we
instead pre-append a fake _nested-name-specifier_ that refers to the
injected-class-name of the enclosing class. This patch also refactors
`Sema::BuildQualifiedDeclarationNameExpr` and
`Sema::BuildQualifiedTemplateIdExpr`, streamlining their implementation
and removing any redundant checks.



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list