-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[clang][Parser] Allow private type aliases in out-of-line member function return types #169272
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
base: main
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -61,8 +61,26 @@ bool Parser::isCXXDeclarationStatement( | |
| // token is also an identifier and assume a declaration. | ||
| // We cannot check if the scopes match because the declarations could | ||
| // involve namespaces and friend declarations. | ||
| if (NextToken().is(tok::identifier)) | ||
| // | ||
| // Also handle cases like "A::B *foo" or "A::B &foo" where the type | ||
| // is followed by ptr/ref declarator operators. These patterns are | ||
| // very likely to be declarations (e.g., out-of-line member function | ||
| // definitions with pointer/reference return types). | ||
| Token Next = NextToken(); | ||
| if (Next.is(tok::identifier)) | ||
| return true; | ||
| // Check for pointer/reference patterns: A::B *id, A::B &id, A::B &&id | ||
| // Also handles multiple indirections like A::B **id | ||
| if (Next.isOneOf(tok::star, tok::amp, tok::ampamp)) { | ||
| // Look ahead to see if there's an identifier after ptr/ref ops | ||
| RevertingTentativeParsingAction PA(*this); | ||
| ConsumeToken(); // consume the identifier (type name) | ||
| // Skip all consecutive *, &, && tokens (for cases like A::B **) | ||
| while (Tok.isOneOf(tok::star, tok::amp, tok::ampamp)) | ||
|
Contributor
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 presume the c++ scope specifier has been parsed already. In this case we should call a parser function rather than implementing some parsing by ourselves. You can trace what clang does for out-of-line definitions after calling |
||
| ConsumeToken(); | ||
| if (Tok.is(tok::identifier)) | ||
| return true; | ||
| } | ||
| } | ||
| break; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // RUN: cat %s | clang-repl | FileCheck %s | ||
|
|
||
| extern "C" int printf(const char*, ...); | ||
|
|
||
| // Test 1: Pointer to private type alias (the original bug report) | ||
| class io_context { using impl_type = int; public: impl_type* get(); }; | ||
| io_context::impl_type* io_context::get() { return nullptr; } | ||
| printf("Pointer to private type: %s\n", io_context().get() == nullptr ? "passed" : "failed"); | ||
| // CHECK: Pointer to private type: passed | ||
|
|
||
| // Test 2: Reference to private type | ||
| class RefReturn { using ref_t = int; ref_t value = 42; public: ref_t& getRef(); }; | ||
| RefReturn::ref_t& RefReturn::getRef() { return value; } | ||
| printf("Reference to private type: %d\n", RefReturn().getRef()); | ||
| // CHECK: Reference to private type: 42 | ||
|
|
||
| // Test 3: Double pointer to private type | ||
| class PtrPtr { using inner_t = int; public: inner_t** get(); }; | ||
| PtrPtr::inner_t** PtrPtr::get() { static int* p = nullptr; return &p; } | ||
| printf("Double pointer to private type: %s\n", PtrPtr().get() != nullptr ? "passed" : "failed"); | ||
| // CHECK: Double pointer to private type: passed | ||
|
|
||
| // Test 4: Const reference to private type | ||
| class ConstRef { using data_t = int; data_t val = 100; public: const data_t& get(); }; | ||
| const ConstRef::data_t& ConstRef::get() { return val; } | ||
| printf("Const reference to private type: %d\n", ConstRef().get()); | ||
| // CHECK: Const reference to private type: 100 | ||
|
|
||
| // Test 5: Pointer to private nested struct | ||
| class Container { struct Node { int x; }; public: Node* create(); }; | ||
| Container::Node* Container::create() { return new Node{789}; } | ||
| printf("Pointer to private nested struct: %d\n", Container().create()->x); | ||
| // CHECK: Pointer to private nested struct: 789 | ||
|
|
||
| %quit |
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.
Let me know if this comment above should be modified \o