From 66e300e6f99c06a489b4cb77245d1667cb46ea3c Mon Sep 17 00:00:00 2001 From: DeLesley Hutchins Date: Fri, 2 Nov 2012 21:44:32 +0000 Subject: [PATCH] Thread safety analysis: Fixed ICE caused by double delete when late parsed attributes are attached to function declarations nested inside a class method. llvm-svn: 167321 --- clang/include/clang/Parse/Parser.h | 11 +++++++++-- clang/lib/Parse/ParseDecl.cpp | 7 +++++-- clang/lib/Parse/ParseTemplate.cpp | 2 +- clang/test/SemaCXX/warn-thread-safety-parsing.cpp | 22 ++++++++++++++++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index e16aead..ef69611 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -848,9 +848,16 @@ private: void addDecl(Decl *D) { Decls.push_back(D); } }; - /// A list of late parsed attributes. Used by ParseGNUAttributes. - typedef llvm::SmallVector LateParsedAttrList; + // A list of late-parsed attributes. Used by ParseGNUAttributes. + class LateParsedAttrList: public llvm::SmallVector { + public: + LateParsedAttrList(bool PSoon = false) : ParseSoon(PSoon) { } + + bool parseSoon() { return ParseSoon; } + private: + bool ParseSoon; // Are we planning to parse these shortly after creation? + }; /// Contains the lexed tokens of a member function definition /// which needs to be parsed at the end of the class declaration diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7b4fbfc2..d45f038 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -143,7 +143,7 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, // Attributes in a class are parsed at the end of the class, along // with other late-parsed declarations. - if (!ClassStack.empty()) + if (!ClassStack.empty() && !LateAttrs->parseSoon()) getCurrentClass().LateParsedDeclarations.push_back(LA); // consume everything up to and including the matching right parens @@ -871,6 +871,8 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { /// \brief Parse all attributes in LAs, and attach them to Decl D. void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, bool EnterScope, bool OnDefinition) { + assert(LAs.parseSoon() && + "Attribute list should be marked for immediate parsing."); for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) { if (D) LAs[i]->addDecl(D); @@ -1413,7 +1415,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // Save late-parsed attributes for now; they need to be parsed in the // appropriate function scope after the function Decl has been constructed. - LateParsedAttrList LateParsedAttrs; + // These will be parsed in ParseFunctionDefinition or ParseLexedAttrList. + LateParsedAttrList LateParsedAttrs(true); if (D.isFunctionDeclarator()) MaybeParseGNUAttributes(D, &LateParsedAttrs); diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 11be360..2e0411e 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -246,7 +246,7 @@ Parser::ParseSingleDeclarationAfterTemplate( return 0; } - LateParsedAttrList LateParsedAttrs; + LateParsedAttrList LateParsedAttrs(true); if (DeclaratorInfo.isFunctionDeclarator()) MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); diff --git a/clang/test/SemaCXX/warn-thread-safety-parsing.cpp b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp index 92c4b10..df9415c 100644 --- a/clang/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -1464,4 +1464,26 @@ class Foo { } // end namespace StaticScopeTest +namespace FunctionAttributesInsideClass_ICE_Test { + +class Foo { +public: + /* Originally found when parsing foo() as an ordinary method after the + * the following: + + template + void syntaxErrorMethod(int i) { + if (i) { + foo( + } + } + */ + + void method() { + void foo() EXCLUSIVE_LOCKS_REQUIRED(mu); // \ + // expected-error {{use of undeclared identifier 'mu'}} + } +}; + +} // end namespace FunctionAttributesInsideClass_ICE_Test -- 2.7.4