From fcbe20811e3848869054ad13352cbb431bd423eb Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 1 Aug 2013 04:22:55 +0000 Subject: [PATCH] Parse: Don't consider attributes of broken member declarators ParseCXXClassMemberDeclaration was trying to use the result of ActOnCXXMemberDeclarator to attach it to some late parsed attributes. However when failures arise, we have no decl to attach to which eventually leads us to a NULL pointer dereference. While we are here, clean up the code a bit. Fixes PR16765 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187557 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseDeclCXX.cpp | 63 +++++++++++++++++----------------- test/Parser/cxx-attributes.cpp | 5 ++- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 7a0cbda1f2..8df15ba75d 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2164,11 +2164,13 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo, VS, DefinitionKind, Init); - for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { - CommonLateParsedAttrs[i]->addDecl(FunDecl); - } - for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) { - LateParsedAttrs[i]->addDecl(FunDecl); + if (FunDecl) { + for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { + CommonLateParsedAttrs[i]->addDecl(FunDecl); + } + for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) { + LateParsedAttrs[i]->addDecl(FunDecl); + } } LateParsedAttrs.clear(); @@ -2262,28 +2264,19 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, TemplateParams, BitfieldSize.release(), VS, HasInClassInit); - if (AccessAttrs) + if (ThisDecl && AccessAttrs) Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs, false, true); } - - // Set the Decl for any late parsed attributes - for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) { - CommonLateParsedAttrs[i]->addDecl(ThisDecl); - } - for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) { - LateParsedAttrs[i]->addDecl(ThisDecl); - } - LateParsedAttrs.clear(); // Handle the initializer. if (HasInClassInit != ICIS_NoInit && DeclaratorInfo.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) { // The initializer was deferred; parse it and cache the tokens. - Diag(Tok, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_nonstatic_member_init : - diag::ext_nonstatic_member_init); + Diag(Tok, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_nonstatic_member_init + : diag::ext_nonstatic_member_init); if (DeclaratorInfo.isArrayOfUnknownBound()) { // C++11 [dcl.array]p3: An array bound may also be omitted when the @@ -2293,37 +2286,45 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // initializer in the grammar, so this is ill-formed. Diag(Tok, diag::err_incomplete_array_member_init); SkipUntil(tok::comma, true, true); + + // Avoid later warnings about a class member of incomplete type. if (ThisDecl) - // Avoid later warnings about a class member of incomplete type. ThisDecl->setInvalidDecl(); } else ParseCXXNonStaticMemberInitializer(ThisDecl); } else if (HasInitializer) { // Normal initializer. if (!Init.isUsable()) - Init = ParseCXXMemberInitializer(ThisDecl, - DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); - + Init = ParseCXXMemberInitializer( + ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); + if (Init.isInvalid()) SkipUntil(tok::comma, true, true); else if (ThisDecl) Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid(), DS.containsPlaceholderType()); - } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) { + } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) // No initializer. Actions.ActOnUninitializedDecl(ThisDecl, DS.containsPlaceholderType()); - } - + if (ThisDecl) { + if (!ThisDecl->isInvalidDecl()) { + // Set the Decl for any late parsed attributes + for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) + CommonLateParsedAttrs[i]->addDecl(ThisDecl); + + for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) + LateParsedAttrs[i]->addDecl(ThisDecl); + } Actions.FinalizeDeclaration(ThisDecl); DeclsInGroup.push_back(ThisDecl); + + if (DeclaratorInfo.isFunctionDeclarator() && + DeclaratorInfo.getDeclSpec().getStorageClassSpec() != + DeclSpec::SCS_typedef) + HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl); } - - if (ThisDecl && DeclaratorInfo.isFunctionDeclarator() && - DeclaratorInfo.getDeclSpec().getStorageClassSpec() - != DeclSpec::SCS_typedef) { - HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl); - } + LateParsedAttrs.clear(); DeclaratorInfo.complete(ThisDecl); diff --git a/test/Parser/cxx-attributes.cpp b/test/Parser/cxx-attributes.cpp index 5ea0ce2275..97380521f8 100644 --- a/test/Parser/cxx-attributes.cpp +++ b/test/Parser/cxx-attributes.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics class c { virtual void f1(const char* a, ...) @@ -8,3 +7,7 @@ class c { __attribute__ (( __format__(__printf__,2,3) )) {} }; +template class X { + template void X::f() __attribute__((locks_excluded())); // expected-error{{nested name specifier 'X::' for declaration does not refer into a class, class template or class template partial specialization}} \ + // expected-warning{{attribute locks_excluded ignored, because it is not attached to a declaration}} +}; -- 2.40.0