diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ad9bb0a6b91fc6d1f11b1c95ac298f56eed142c8..dd9508e3a08ad6a218fedf495bb6029c06339892 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 20b40259a8c8a59a1a947ebc41d0b5602c7d5bbc..2b3f18aa00a5c384c92df0be4f4936234669e83f 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 0677d7e95cdcae9cd84f7dc93703f59958b3417f..5a837692ec0332b22b98cf05667b7b80cd4b11e0 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 c199139b9f729192f946f80f5fa7b1dc58a8071c..2ff1ee7ba8f13fd53199b3476b86fbd6a3f1e00a 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 3494c223d16c5a76f9f95cc3761ba666d9a1657a..13bd298fce864b16d39fadd7d27a413d880ebe97 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 ea9aeedc9fe5c039db931790879a2c7b584ca8aa..f4115790ab3791e7a6a6f6dc426d17e7623355ab 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. -*/