From: Nico Weber Date: Mon, 16 Feb 2015 22:32:46 +0000 (+0000) Subject: For variables with dependent type, don't crash on `var->::new` or `var->__super` X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fffe56ebdc121f2666d46663ee106dd2a576db27;p=clang For variables with dependent type, don't crash on `var->::new` or `var->__super` ParsePostfixExpressionSuffix() for '->' (or '.') postfixes first calls ActOnStartCXXMemberReference() to inform sema that a member reference is about to start, and that function lets the parser know if sema thinks that the base expression's type could allow a pseudo destructor from a semantic point of view (for example, if the the base expression has a dependent type). ParsePostfixExpressionSuffix() then calls ParseOptionalCXXScopeSpecifier() and passes MayBePseudoDestructor on to that function, expecting the function to set it to false if a pseudo destructor is impossible from a syntactic point of view (due to a lack of '~' sigil). However, ParseOptionalCXXScopeSpecifier() had early-outs for ::new and __super, so MayBePseudoDestructor stayed true, so we tried to parse a pseudo dtor, and then became confused since we couldn't find a '~'. Move the snippet in ParseOptionalCXXScopeSpecifier() that sets MayBePseudoDestructor to false above the early exits. Parts of this found by SLi's bot. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@229449 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index e7ca66de48..d91744115c 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -194,6 +194,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (Tok.is(tok::annot_cxxscope)) { assert(!LastII && "want last identifier but have already annotated scope"); + assert(!MayBePseudoDestructor && "unexpected annot_cxxscope"); Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); @@ -208,6 +209,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, SS = TemplateId->SS; } + // Has to happen before any "return false"s in this function. + bool CheckForDestructor = false; + if (MayBePseudoDestructor && *MayBePseudoDestructor) { + CheckForDestructor = true; + *MayBePseudoDestructor = false; + } + if (LastII) *LastII = nullptr; @@ -244,12 +252,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return Actions.ActOnSuperScopeSpecifier(SuperLoc, ConsumeToken(), SS); } - bool CheckForDestructor = false; - if (MayBePseudoDestructor && *MayBePseudoDestructor) { - CheckForDestructor = true; - *MayBePseudoDestructor = false; - } - if (!HasScopeSpecifier && (Tok.is(tok::kw_decltype) || Tok.is(tok::annot_decltype))) { DeclSpec DS(AttrFactory); diff --git a/test/SemaCXX/MicrosoftSuper.cpp b/test/SemaCXX/MicrosoftSuper.cpp index cb21656ab7..df63691812 100644 --- a/test/SemaCXX/MicrosoftSuper.cpp +++ b/test/SemaCXX/MicrosoftSuper.cpp @@ -147,3 +147,12 @@ void instantiate() { DerivedFromTemplateParameter t; t.foo(); } + +namespace { +struct B { int a; }; +template +struct A : B { + // Don't crash on dependent_type_var '->' '__super' + void f() { int a = this->__super::a; } +}; +} diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index cb43458d45..7bc724b210 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -524,3 +524,11 @@ namespace PR18544 { // PR19968 inline void* operator new(); // expected-error {{'operator new' must have at least one parameter}} + +namespace { +template +struct A { + void f() { this->::new; } // expected-error {{expected unqualified-id}} + void g() { this->::delete; } // expected-error {{expected unqualified-id}} +}; +}