diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1564,6 +1564,9 @@ QualType getEnumType(const EnumDecl *Decl) const; + QualType + getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const; + QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const; QualType getAttributedType(attr::Kind attrKind, diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -358,7 +358,7 @@ } def : Creator<[{ - return ctx.getTypeDeclType(cast(declaration)); + return ctx.getUnresolvedUsingType(cast(declaration)); }]>; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4568,9 +4568,7 @@ assert(Enum->isFirstDecl() && "enum has previous declaration"); return getEnumType(Enum); } else if (const auto *Using = dyn_cast(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?"); @@ -4619,6 +4617,22 @@ 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) { diff --git a/clang/test/Modules/Inputs/odr_using_dependent_name/X.cppm b/clang/test/Modules/Inputs/odr_using_dependent_name/X.cppm new file mode 100644 --- /dev/null +++ b/clang/test/Modules/Inputs/odr_using_dependent_name/X.cppm @@ -0,0 +1,3 @@ +module; +#include "foo.h" +export module X; diff --git a/clang/test/Modules/Inputs/odr_using_dependent_name/foo.h b/clang/test/Modules/Inputs/odr_using_dependent_name/foo.h new file mode 100644 --- /dev/null +++ b/clang/test/Modules/Inputs/odr_using_dependent_name/foo.h @@ -0,0 +1,9 @@ +template +struct bar { + using Ty = int; +}; +template +struct foo : public bar { + using typename bar::Ty; + void baz(Ty); +}; diff --git a/clang/test/Modules/odr_using_dependent_name.cppm b/clang/test/Modules/odr_using_dependent_name.cppm new file mode 100644 --- /dev/null +++ b/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;