ChuanqiXu created this revision. ChuanqiXu added reviewers: rsmith, aaron.ballman, urnathan, erichkeane, tbaeder. ChuanqiXu added a project: clang. ChuanqiXu requested review of this revision. Herald added a subscriber: cfe-commits.
Since only the decls inhabit in a namespace scope could be exported, it is not meaningful to check it in CheckRedeclarationExported, which implements [module.interface]/p6: http://eel.is/c++draft/module.interface#6. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D118120 Files: clang/lib/Sema/SemaDecl.cpp clang/test/CXX/module/module.interface/p6.cpp Index: clang/test/CXX/module/module.interface/p6.cpp =================================================================== --- clang/test/CXX/module/module.interface/p6.cpp +++ clang/test/CXX/module/module.interface/p6.cpp @@ -91,3 +91,24 @@ T TemplVar; // expected-note {{previous declaration is here}} export template <typename T> T TemplVar; // expected-error {{cannot export redeclaration 'TemplVar' here since the previous declaration is not exported}} + +// Test the compiler wouldn't complain about the redeclaration of friend in exported class. +namespace Friend { +template <typename T> +class bar; +class gua; +template <typename T> +void hello(); +void hi(); +export class foo; +bool operator<(const foo &a, const foo &b); +export class foo { + template <typename T> + friend class bar; + friend class gua; + template <typename T> + friend void hello(); + friend void hi(); + friend bool operator<(const foo &a, const foo &b); +}; +} // namespace Friend Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -1635,6 +1635,19 @@ // A redeclaration of an entity X is implicitly exported if X was introduced by // an exported declaration; otherwise it shall not be exported. bool Sema::CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old) { + // [module.interface]p1: + // An export-declaration shall inhabit a namespace scope. + // + // So it is meaningless to talk about redeclaration which is not at namespace + // scope. + if (!New->getLexicalDeclContext() + ->getNonTransparentContext() + ->isFileContext() || + !Old->getLexicalDeclContext() + ->getNonTransparentContext() + ->isFileContext()) + return false; + bool IsNewExported = New->isInExportDeclContext(); bool IsOldExported = Old->isInExportDeclContext();
Index: clang/test/CXX/module/module.interface/p6.cpp =================================================================== --- clang/test/CXX/module/module.interface/p6.cpp +++ clang/test/CXX/module/module.interface/p6.cpp @@ -91,3 +91,24 @@ T TemplVar; // expected-note {{previous declaration is here}} export template <typename T> T TemplVar; // expected-error {{cannot export redeclaration 'TemplVar' here since the previous declaration is not exported}} + +// Test the compiler wouldn't complain about the redeclaration of friend in exported class. +namespace Friend { +template <typename T> +class bar; +class gua; +template <typename T> +void hello(); +void hi(); +export class foo; +bool operator<(const foo &a, const foo &b); +export class foo { + template <typename T> + friend class bar; + friend class gua; + template <typename T> + friend void hello(); + friend void hi(); + friend bool operator<(const foo &a, const foo &b); +}; +} // namespace Friend Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -1635,6 +1635,19 @@ // A redeclaration of an entity X is implicitly exported if X was introduced by // an exported declaration; otherwise it shall not be exported. bool Sema::CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old) { + // [module.interface]p1: + // An export-declaration shall inhabit a namespace scope. + // + // So it is meaningless to talk about redeclaration which is not at namespace + // scope. + if (!New->getLexicalDeclContext() + ->getNonTransparentContext() + ->isFileContext() || + !Old->getLexicalDeclContext() + ->getNonTransparentContext() + ->isFileContext()) + return false; + bool IsNewExported = New->isInExportDeclContext(); bool IsOldExported = Old->isInExportDeclContext();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits