This is an archive of the discontinued LLVM Phabricator instance.

PR23175 (fix) - Infinite loop iterating Objective-C method declarations in categories when the AST was deserialized from an .ast file
AcceptedPublic

Authored by tahonermann on Apr 20 2015, 2:02 PM.

Details

Reviewers
klimek
rsmith
Summary

This patch corrects several errors that result in incorrect Objective-C method declaration enumeration that occurs when an AST is deserialized from an .ast file.

There were two issues:

  1. In lib/AST/DeclObjC.cpp, in ObjCImplDecl::setClassInterface(), the base class version (ObjCImplDecl) of (non-virtual) getIdentifier() was being called, but the derived class version (ObjCCategoryImplDecl) is what is required. See this comment in include/clang/AST/DeclObjC.h: class ObjCCategoryImplDecl : public ObjCImplDecl { ... / getIdentifier - Get the identifier that names the category / interface associated with this implementation. / FIXME: This is a bad API, we are hiding NamedDecl::getIdentifier() / with a different meaning. For example: / ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier() / returns the class interface name, whereas / ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier() / returns the category name. IdentifierInfo *getIdentifier() const { return Id; } I did not change the interface, but clearly, it would be a good idea to do so. The patch uses the existing downcasted pointer to call the correct version.
  1. With the above change, when deserializing a ObjCCategoryImplDecl instance, ObjCImplDecl::setClassInterface() was being called by ASTDeclReader::VisitObjCImplDecl() before the category name was deserialized in ASTDeclReader::VisitObjCCategoryImplDecl(). The patch delays the call to ObjCImplDecl::setClassInterface() until after the category name is deserialized and set.

Diff Detail

Repository
rL LLVM

Event Timeline

tahonermann retitled this revision from to PR23175 (fix) - Infinite loop iterating Objective-C method declarations in categories when the AST was deserialized from an .ast file.
tahonermann updated this object.
tahonermann edited the test plan for this revision. (Show Details)
tahonermann added a reviewer: klimek.
tahonermann set the repository for this revision to rL LLVM.
tahonermann added a subscriber: Unknown Object (MLST).

The formatting I intended in the summary did not take affect. Here is the referenced code as I intended it to display:

See this comment in include/clang/AST/DeclObjC.h:

class ObjCCategoryImplDecl : public ObjCImplDecl {
...
/// getIdentifier - Get the identifier that names the category
/// interface associated with this implementation.
/// FIXME: This is a bad API, we are hiding NamedDecl::getIdentifier()
/// with a different meaning. For example:
/// ((NamedDecl *)SomeCategoryImplDecl)->getIdentifier()
/// returns the class interface name, whereas
/// ((ObjCCategoryImplDecl *)SomeCategoryImplDecl)->getIdentifier()
/// returns the category name.
IdentifierInfo *getIdentifier() const {
  return Id;
}

I did not change the interface, but clearly, it would be a good idea to do so. The patch uses the existing downcasted pointer to call the correct version.

tahonermann added inline comments.Apr 20 2015, 2:07 PM
lib/AST/DeclObjC.cpp
1745

The subtle fix. Calling ImplD->getIdentifier() is required to get the category name. this->getIdentifier() returns the class name.

rsmith edited edge metadata.Apr 21 2015, 4:03 PM

Please add a testcase (I'd imagine it's not too hard to craft one in this case?).

lib/AST/DeclObjC.cpp
1745

Ouch. Can I tempt you to work on fixing the hiding of getIdentifier after this patch lands? :)

lib/Serialization/ASTReaderDecl.cpp
984–985

Don't add PR references to the code; your comments should be complete enough to explain why we're doing what we're doing now without reference to what we got wrong before. In this case, I think they are. (People interested in the code's history can check the SVN logs.)

Please add a testcase (I'd imagine it's not too hard to craft one in this case?).

I had posted the test case separately. You can find it in D9126. I had to craft a unit test. I couldn't find a way to exploit the problem from just the Clang command line.

lib/AST/DeclObjC.cpp
1745

Oh, I was already tempted. I'll try and find some time to fix it. I'll be surprised if there aren't other cases like this waiting to be found.

lib/Serialization/ASTReaderDecl.cpp
984–985

Funny. Usually I'm the one telling people not to add such references. Would you like me to repost the patch with the PR reference removed?

rsmith accepted this revision.Apr 21 2015, 6:51 PM
rsmith edited edge metadata.

OK, the combination of these two changes LGTM (modulo renaming the test file and removing the PR number). For future reference, it's our convention to include the code change and tests in the same review.

Do you need someone to commit this for you?

lib/Serialization/ASTReaderDecl.cpp
984–985

Nah, whoever commits can just do that before checkin.

This revision is now accepted and ready to land.Apr 21 2015, 6:51 PM

For future reference, it's our convention to include the code change and tests in the same review.

Thanks, I'll do so in the future.

Do you need someone to commit this for you?

Yes, please. I don't have commit access.

klimek added a comment.Jul 3 2015, 6:59 AM

Richard, was there a reason you didn't submit this?

Looks like patch was not committed.

For what it's worth, Coverity has been running with this patch in place for at least a year and a half now. I believe the only reason it wasn't committed was due to concerns with the test case in D9126. I haven't had time to address those concerns (and don't expect to anytime soon).