From: Kaelyn Uhrain Date: Thu, 19 Apr 2012 23:17:45 +0000 (+0000) Subject: In Parser::isCXXDeclarationSpecifier, consider a non-type identifier X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=434ed260eb28cacd1b87fc2429dfee66d61dfcf0;p=clang In Parser::isCXXDeclarationSpecifier, consider a non-type identifier followed by an identifier as declaration specificer (except for ObjC). This allows e.g. an out-of-line C++ member function definitions to be recognized as functions and not as variable declarations if the type name for the first parameter is not recognized as a type--say, when there is a function name shadowing an enum type name and the parameter is missing the "enum" keyword needed to distinguish the two. Note that returning TPResult::Error() instead of TPResult::True() appears to have the same end result, while TPResult::Ambiguous() results in a crash. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155163 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 28c5e8b673..b5251a6177 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -931,8 +931,12 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult) { // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) return TPResult::Error(); - if (Tok.is(tok::identifier)) - return TPResult::False(); + if (Tok.is(tok::identifier)) { + const Token &Next = NextToken(); + bool NotObjC = !(getLangOpts().ObjC1 || getLangOpts().ObjC2); + return (NotObjC && Next.is(tok::identifier)) ? + TPResult::True() : TPResult::False(); + } return isCXXDeclarationSpecifier(BracedCastResult); case tok::coloncolon: { // ::foo::bar diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp index 7d531a537a..afa71c6f3d 100644 --- a/test/FixIt/fixit.cpp +++ b/test/FixIt/fixit.cpp @@ -204,3 +204,15 @@ template Foo, // expected-error {{template template parameter template typename Bar, // expected-error {{template template parameter requires 'class' after the parameter list}} template struct Baz> // expected-error {{template template parameter requires 'class' after the parameter list}} void func(); + + +namespace ShadowedTagType { +class Foo { + public: + enum Bar { X, Y }; + void SetBar(Bar bar); + Bar Bar(); + private: + Bar bar_; // expected-error {{must use 'enum' tag to refer to type 'Bar' in this scope}} +}; +void Foo::SetBar(Bar bar) { bar_ = bar; } // expected-error {{must use 'enum' tag to refer to type 'Bar' in this scope}}