diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 725bb0bced9c57..baed5ca22fa758 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -3287,8 +3287,12 @@ class ConceptDecl : public TemplateDecl, public Mergeable { return isa(getTemplateParameters()->getParam(0)); } - ConceptDecl *getCanonicalDecl() override { return getFirstDecl(); } - const ConceptDecl *getCanonicalDecl() const { return getFirstDecl(); } + ConceptDecl *getCanonicalDecl() override { + return cast(getPrimaryMergedDecl(this)); + } + const ConceptDecl *getCanonicalDecl() const { + return const_cast(this)->getCanonicalDecl(); + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8f887ce7829fa2..c0bec60f737c88 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8754,7 +8754,8 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, // Other decls (e.g. namespaces) also have this shortcoming. return; } - Context.setPrimaryMergedDecl(NewDecl, OldConcept); + // We unwrap canonical decl late to check for module visibility. + Context.setPrimaryMergedDecl(NewDecl, OldConcept->getCanonicalDecl()); } /// \brief Strips various properties off an implicit instantiation diff --git a/clang/test/Modules/merge-concepts.cpp b/clang/test/Modules/merge-concepts.cpp index 9242f27633795b..c774157dd85b4e 100644 --- a/clang/test/Modules/merge-concepts.cpp +++ b/clang/test/Modules/merge-concepts.cpp @@ -28,6 +28,10 @@ module "library" { export * header "concepts.h" } + module "compare" { + export * + header "compare.h" + } module "format" { export * header "format.h" @@ -47,19 +51,34 @@ module "library" { #define SAME_AS_H template -concept same_as = __is_same(T, U); +concept same_as_impl = __is_same(T, U); +template +concept same_as = same_as_impl && same_as_impl; #endif // SAME_AS_H + +//--- compare.h +#ifndef COMPARE_H +#define COMPARE_H + +#include "same_as.h" +#include "concepts.h" + +template void foo() + requires same_as +{} +#endif // COMPARE_H + //--- format.h #ifndef FORMAT_H #define FORMAT_H -#include "concepts.h" #include "same_as.h" +#include "concepts.h" -template void foo() +template void bar() requires same_as {} -#endif // FORMAT_H \ No newline at end of file +#endif // FORMAT_H