From: Richard Smith Date: Tue, 28 Oct 2014 16:55:02 +0000 (+0000) Subject: PR21367: Don't accept rvalue references as an extension in C++98 mode if we're in... X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0b350b9ec54e4fa762772688d27e38556af4f83b;p=platform%2Fupstream%2Fllvm.git PR21367: Don't accept rvalue references as an extension in C++98 mode if we're in a new-type-id or conversion-type-id, since those things can legitimately be followed by a binary && operator. llvm-svn: 220785 --- diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 054df9f..2288cb1 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4527,15 +4527,27 @@ void Parser::ParseDeclarator(Declarator &D) { ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); } -static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang) { +static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, + unsigned TheContext) { if (Kind == tok::star || Kind == tok::caret) return true; - // We parse rvalue refs in C++03, because otherwise the errors are scary. if (!Lang.CPlusPlus) return false; - return Kind == tok::amp || Kind == tok::ampamp; + if (Kind == tok::amp) + return true; + + // We parse rvalue refs in C++03, because otherwise the errors are scary. + // But we must not parse them in conversion-type-ids and new-type-ids, since + // those can be legitimately followed by a && operator. + // (The same thing can in theory happen after a trailing-return-type, but + // since those are a C++11 feature, there is no rejects-valid issue there.) + if (Kind == tok::ampamp) + return Lang.CPlusPlus11 || (TheContext != Declarator::ConversionIdContext && + TheContext != Declarator::CXXNewContext); + + return false; } /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator @@ -4615,7 +4627,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, tok::TokenKind Kind = Tok.getKind(); // Not a pointer, C++ reference, or block. - if (!isPtrOperatorToken(Kind, getLangOpts())) { + if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) { if (DirectDeclParser) (this->*DirectDeclParser)(D); return; @@ -4810,7 +4822,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { !D.hasGroupingParens() && !Actions.containsUnexpandedParameterPacks(D))) { SourceLocation EllipsisLoc = ConsumeToken(); - if (isPtrOperatorToken(Tok.getKind(), getLangOpts())) { + if (isPtrOperatorToken(Tok.getKind(), getLangOpts(), D.getContext())) { // The ellipsis was put in the wrong place. Recover, and explain to // the user what they should have done. ParseDeclarator(D); diff --git a/clang/test/Parser/cxx0x-in-cxx98.cpp b/clang/test/Parser/cxx0x-in-cxx98.cpp index 7249938..10cb4d2 100644 --- a/clang/test/Parser/cxx0x-in-cxx98.cpp +++ b/clang/test/Parser/cxx0x-in-cxx98.cpp @@ -28,3 +28,7 @@ struct Auto { auto Auto::n = 0; // expected-warning {{'auto' type specifier is a C++11 extension}} auto Auto::m = 0; // expected-error {{no member named 'm' in 'Auto'}} // expected-warning@-1 {{'auto' type specifier is a C++11 extension}} + +struct Conv { template operator T(); }; +bool pr21367_a = new int && false; +bool pr21367_b = &Conv::operator int && false;