From 7b1bdb01c997fddb9661f45048c46b75755906f5 Mon Sep 17 00:00:00 2001 From: milmou Date: Sat, 25 Feb 2023 09:09:53 +0800 Subject: [PATCH] [BSC] New parse logic for BSCMethod fixed a bug caused by using Parser::GetLookAheadToken --- clang/include/clang/Parse/Parser.h | 28 +++++++++++++++++++++++++- clang/lib/Parse/ParseDecl.cpp | 23 +++++++++++++++++++-- clang/test/BSC/Method/definition_1.cbs | 7 +++++++ clang/test/BSC/Method/definition_2.cbs | 11 +++------- clang/test/BSC/Method/definition_3.cbs | 11 +++------- clang/test/BSC/Method/definition_4.cbs | 11 +++------- 6 files changed, 64 insertions(+), 27 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ad9bb0a6b91f..dd9508e3a08a 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -484,6 +484,31 @@ public: return PrevTokLocation; } + /// Judge whether there is a \param FindToken before \param StopToken. + bool FindUntil(tok::TokenKind FindToken, + tok::TokenKind StopToken1 = tok::eof, + tok::TokenKind StopToken2 = tok::l_brace, + tok::TokenKind StopToken3 = tok::equal) { + std::vector Tokens; + bool FindFlag = false; + + while (1) { + if (Tok.isOneOf(StopToken1, StopToken2, StopToken3)) + break; + if (Tok.is(FindToken)) { + FindFlag = true; + break; + } + Tokens.push_back(Tok); + ConsumeAnyToken(); + } + + for (int i = Tokens.size() - 1; i >= 0; i-- ) { + UnconsumeToken(Tokens[i]); + } + return FindFlag; + } + bool TryConsumeToken(tok::TokenKind Expected) { if (Tok.isNot(Expected)) return false; @@ -2356,7 +2381,8 @@ private: const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none, DeclSpecContext DSC = DeclSpecContext::DSC_normal, - LateParsedAttrList *LateAttrs = nullptr, bool BSCMethodFlag = false); + LateParsedAttrList *LateAttrs = nullptr, bool BSCScopeSpecFlag = false, + bool BSCMethodFlag = false); void ParseBSCScopeSpecifiers(DeclSpec &DS); bool DiagnoseMissingSemiAfterTagDefinition( DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 20b40259a8c8..2b3f18aa00a5 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3003,7 +3003,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs, - bool BSCMethodFlag) { + bool BSCScopeSpecFlag, + bool BSCMethodFlag) { + if (getLangOpts().BSC && !BSCScopeSpecFlag) + BSCMethodFlag = FindUntil(tok::coloncolon); if (DS.getSourceRange().isInvalid()) { // Start the range at the current token but make the end of the range // invalid. This will make the entire range invalid unless we successfully @@ -3051,6 +3054,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation Loc = Tok.getLocation(); + if (BSCMethodFlag && DS.hasTypeSpecifier()) { + if (!AttrsLastTime) + ProhibitAttributes(attrs); + else { + ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr); + DS.takeAttributesFrom(attrs); + } + + DS.Finish(Actions, Policy); + return; + } + switch (Tok.getKind()) { default: DoneWithDeclSpec: @@ -3121,6 +3136,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::coloncolon: // ::foo::bar // C++ scope specifier. Annotate and loop, or bail out on error. + if (BSCScopeSpecFlag) + goto DoneWithDeclSpec; if (TryAnnotateCXXScopeToken(EnteringContext)) { if (!DS.hasTypeSpecifier()) DS.SetTypeSpecError(); @@ -5695,7 +5712,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.setExtension(); // BSC - if (getLangOpts().BSC && (NextToken().is(tok::coloncolon) || GetLookAheadToken(2).is(tok::coloncolon))) { + if (getLangOpts().BSC && + (Tok.isNot(tok::identifier) || + (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)))) { BSCScopeSpec BSS(*this); ParseBSCScopeSpecifiers(BSS); TryConsumeToken(tok::coloncolon); diff --git a/clang/test/BSC/Method/definition_1.cbs b/clang/test/BSC/Method/definition_1.cbs index 0677d7e95cdc..5a837692ec03 100644 --- a/clang/test/BSC/Method/definition_1.cbs +++ b/clang/test/BSC/Method/definition_1.cbs @@ -1,3 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + struct Foo1 { int a; }; @@ -50,6 +53,10 @@ int short::getA0() { return 0; } +unsigned long int::getAa() { + return 0; +} + int main() { return 0; } diff --git a/clang/test/BSC/Method/definition_2.cbs b/clang/test/BSC/Method/definition_2.cbs index c199139b9f72..2ff1ee7ba8f1 100644 --- a/clang/test/BSC/Method/definition_2.cbs +++ b/clang/test/BSC/Method/definition_2.cbs @@ -1,14 +1,9 @@ -int struct Foo::getA() { +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int struct Foo::getA() { // expected-error {{ variable has incomplete type 'struct Foo'}} return 0; } int main() { return 0; } - -/* -definition_2.cbs:1:5: error: variable has incomplete type 'struct Foo' -int struct Foo::getA() { - ^ -1 error generated. -*/ diff --git a/clang/test/BSC/Method/definition_3.cbs b/clang/test/BSC/Method/definition_3.cbs index 3494c223d16c..13bd298fce86 100644 --- a/clang/test/BSC/Method/definition_3.cbs +++ b/clang/test/BSC/Method/definition_3.cbs @@ -1,16 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + struct Foo; -int struct Foo::getA() { +int struct Foo::getA() { // expected-error {{variable has incomplete type 'struct Foo'}} return 0; } int main() { return 0; } - -/* -definition_3.cbs:3:5: error: variable has incomplete type 'struct Foo' -int struct Foo::getA() { - ^ -1 error generated. -*/ diff --git a/clang/test/BSC/Method/definition_4.cbs b/clang/test/BSC/Method/definition_4.cbs index ea9aeedc9fe5..f4115790ab37 100644 --- a/clang/test/BSC/Method/definition_4.cbs +++ b/clang/test/BSC/Method/definition_4.cbs @@ -1,14 +1,9 @@ -int void::getA() { +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int void::getA() { // expected-error {{variable has incomplete type 'viod'}} return 0; } int main() { return 0; } - -/* -definition_4.cbs:1:5: error: variable has incomplete type 'void' -int void::getA() { - ^ -1 error generated. -*/ -- Gitee