Skip to content

Commit

Permalink
[Sema]Use tag name lookup for class names (llvm#112166)
Browse files Browse the repository at this point in the history
This PR would fix llvm#16855 .

The correct lookup to use for class names is Tag name lookup,
because it does not take namespaces into account. The lookup before
does and because of this some valid programs are not accepted.

An example scenario of a valid program being declined is when you have a struct (let's call it `y`) inheriting from another struct with a name `x` but the struct `y` is in a namespace that is also called `x`:
```
struct x
{};

namespace
{
    namespace x
    {
        struct y : x
        {};
    }
}
```

This shall be accepted because: 
```
C++ [class.derived]p2 (wrt lookup in a base-specifier): The lookup for
  // the component name of the type-name or simple-template-id is type-only.
```
  • Loading branch information
spaits authored and DanielCChen committed Oct 16, 2024
1 parent 68f66ba commit 4f63e44
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 5 deletions.
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ Bug Fixes to C++ Support
- Fixed a bug in lambda captures where ``constexpr`` class-type objects were not properly considered ODR-used in
certain situations. (#GH47400), (#GH90896)
- Fix erroneous templated array size calculation leading to crashes in generated code. (#GH41441)
- During the lookup for a base class name, non-type names are ignored. (#GH16855)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,13 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
return nullptr;
}

// FIXME: LookupNestedNameSpecifierName isn't the right kind of
// lookup for class-names.
LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName :
LookupOrdinaryName;
// In the case where we know that the identifier is a class name, we know that
// it is a type declaration (struct, class, union or enum) so we can use tag
// name lookup.
//
// C++ [class.derived]p2 (wrt lookup in a base-specifier): The lookup for
// the component name of the type-name or simple-template-id is type-only.
LookupNameKind Kind = isClassName ? LookupTagName : LookupOrdinaryName;
LookupResult Result(*this, &II, NameLoc, Kind);
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
Expand Down
14 changes: 13 additions & 1 deletion clang/test/CXX/class.derived/p2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,16 @@ namespace PR5840 {
struct Base {};
int Base = 10;
struct Derived : Base {};
}
} // namespace PR5840

namespace issue_16855 {
struct x {};
namespace
{
namespace x
{
struct y : x
{};
} // namespace x
}
} // namespace issue_16855

0 comments on commit 4f63e44

Please sign in to comment.