Skip to content

Commit

Permalink
[Modules] Incorrect ODR detection for unresolved using type
Browse files Browse the repository at this point in the history
Implement `getUnresolvedUsingType()` and don't create a new
`UnresolvedUsingType` when there is already canonical declaration.

This solved an incorrect ODR detection in modules for uresolved using
type.

Reviewed By: rjmccall

Differential Revision: https://reviews.llvm.org/D115792
  • Loading branch information
ChuanqiXu9 committed Dec 17, 2021
1 parent ae6961d commit c50a4b3
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 4 deletions.
3 changes: 3 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Expand Up @@ -1564,6 +1564,9 @@ class ASTContext : public RefCountedBase<ASTContext> {

QualType getEnumType(const EnumDecl *Decl) const;

QualType
getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const;

QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;

QualType getAttributedType(attr::Kind attrKind,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/TypeProperties.td
Expand Up @@ -358,7 +358,7 @@ let Class = UnresolvedUsingType in {
}

def : Creator<[{
return ctx.getTypeDeclType(cast<UnresolvedUsingTypenameDecl>(declaration));
return ctx.getUnresolvedUsingType(cast<UnresolvedUsingTypenameDecl>(declaration));
}]>;
}

Expand Down
20 changes: 17 additions & 3 deletions clang/lib/AST/ASTContext.cpp
Expand Up @@ -4568,9 +4568,7 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const {
assert(Enum->isFirstDecl() && "enum has previous declaration");
return getEnumType(Enum);
} else if (const auto *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Using);
Decl->TypeForDecl = newType;
Types.push_back(newType);
return getUnresolvedUsingType(Using);
} else
llvm_unreachable("TypeDecl without a type?");

Expand Down Expand Up @@ -4619,6 +4617,22 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
return QualType(newType, 0);
}

QualType ASTContext::getUnresolvedUsingType(
const UnresolvedUsingTypenameDecl *Decl) const {
if (Decl->TypeForDecl)
return QualType(Decl->TypeForDecl, 0);

if (const UnresolvedUsingTypenameDecl *CanonicalDecl =
Decl->getCanonicalDecl())
if (CanonicalDecl->TypeForDecl)
return QualType(Decl->TypeForDecl = CanonicalDecl->TypeForDecl, 0);

Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Decl);
Decl->TypeForDecl = newType;
Types.push_back(newType);
return QualType(newType, 0);
}

QualType ASTContext::getAttributedType(attr::Kind attrKind,
QualType modifiedType,
QualType equivalentType) {
Expand Down
3 changes: 3 additions & 0 deletions clang/test/Modules/Inputs/odr_using_dependent_name/X.cppm
@@ -0,0 +1,3 @@
module;
#include "foo.h"
export module X;
9 changes: 9 additions & 0 deletions clang/test/Modules/Inputs/odr_using_dependent_name/foo.h
@@ -0,0 +1,9 @@
template <class T>
struct bar {
using Ty = int;
};
template <class T>
struct foo : public bar<T> {
using typename bar<T>::Ty;
void baz(Ty);
};
9 changes: 9 additions & 0 deletions clang/test/Modules/odr_using_dependent_name.cppm
@@ -0,0 +1,9 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: %clang -std=c++20 %S/Inputs/odr_using_dependent_name/X.cppm --precompile -o %t/X.pcm
// RUN: %clang -std=c++20 -I%S/Inputs/odr_using_dependent_name -fprebuilt-module-path=%t %s --precompile -c
// expected-no-diagnostics
module;
#include "foo.h"
export module Y;
import X;

0 comments on commit c50a4b3

Please sign in to comment.