-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Clang] Fix Microsoft ABI inheritance model when member pointer is used in a base specifier #91990
base: main
Are you sure you want to change the base?
Changes from all commits
5dc9193
85a823a
f343670
ff6a2b8
66c8658
7058fb4
7c619ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
// RUN: %clang_cc1 -verify -fsyntax-only -fcomplete-member-pointers %s | ||
// RUN: %clang_cc1 -verify -fsyntax-only -fc++-abi=itanium -fms-extensions -fcomplete-member-pointers %s | ||
// RUN: %clang_cc1 -verify -fsyntax-only -triple=x86_64-unknown-win32 -fc++-abi=microsoft -fms-compatibility -fcomplete-member-pointers %s | ||
// RUN: %clang_cc1 -verify -fsyntax-only -triple=x86_64-unknown-win32 -fc++-abi=itanium -fms-compatibility -fcomplete-member-pointers %s | ||
|
||
struct S; // expected-note {{forward declaration of 'S'}} | ||
typedef int S::*t; | ||
|
@@ -13,3 +15,18 @@ template <typename T> | |
struct S3 { | ||
int T::*foo; | ||
}; | ||
|
||
template<int I> struct Base {}; | ||
struct | ||
S5 // #S5 | ||
: | ||
Base<sizeof(int S5::*)> | ||
// expected-error@-1 {{member pointer has incomplete base type 'S5'}} | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be an error in Microsoft mode? Shouldn't we silently use the unspecified model in that mode? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's an error for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree on the desired behavior, but doesn't this test show that, in the MS ABI mode, clang emits a hard error about an incomplete type? That's my reading of what the code does, and what the test shows. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's just how |
||
}; | ||
|
||
template<typename T> struct S6 {}; | ||
int S6<void>::* qux; // #qux | ||
template<> struct S6<void> {}; | ||
// expected-error@-1 {{explicit specialization of 'S6<void>' after instantiation}} | ||
// expected-note@#qux {{implicit instantiation first required here}} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,6 +215,14 @@ struct NewUnspecified; | |
SingleTemplate<void (IncSingle::*)()> tmpl_single; | ||
UnspecTemplate<void (NewUnspecified::*)()> tmpl_unspec; | ||
|
||
// Member pointers used in base specifiers force an unspecified inheritance model | ||
struct MemPtrInBase : UnspecTemplate<void (MemPtrInBase::*)()> {}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this memptr type is not required to be complete during the parsing of the base specifiers here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not for simply naming the type for the template argument but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but it's not clear to me if that happens before or after we've finished parsing the base specifiers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see what you mean. However, they need to be instantiated at least before the body of the struct is parsed (because the bases affect name lookup), and this is essentially the same time as when you are "parsing the base specifiers". |
||
#ifdef VMB | ||
struct __single_inheritance SpecifiedMemPtrInBase; | ||
struct SpecifiedMemPtrInBase : SingleTemplate<void (SpecifiedMemPtrInBase::*)()> {}; | ||
struct __single_inheritance SpecifiedMemPtrInBase2 : SingleTemplate<void (SpecifiedMemPtrInBase2::*)()> {}; | ||
#endif | ||
|
||
struct NewUnspecified { }; | ||
|
||
static_assert(sizeof(void (NewUnspecified::*)()) == kUnspecifiedFunctionSize, ""); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Combine these into a single statement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really only want to call
RequireCompleteType
in the else branch when!RD->isBeingDefined()
(when called whileRD->isParsingBaseSpecifiers()
, there's an extra note 'definition of "[class name]" is incomplete until the closing "}"', which is misleading since for CompleteMemberPointers purposes it's complete after the bases are parsed)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm struggling to understand why this error diagnostic doesn't fire in your MS ABI test case example that forms a member pointer type in the base specifier list.