This is an archive of the discontinued LLVM Phabricator instance.

Allow getRawCommentForDecl to find comments in macros
ClosedPublic

Authored by danakj on Jan 25 2023, 8:56 AM.

Details

Summary

The key part of getRawCommentForDecl() required to find a comment
is determining where to look for it. The location of the decl
itself is usually right, except when macros get involved. The
comment in the macro is stored in RawCommentList at the spelling
location of the decl, not at the place where the decl comes into
being as the macro is instantiated.

getDeclLocForCommentSearch() already contained to branches to try
handle comments inside macros, and we are able to replace them
and handle more cases as well, by returning the spelling location
of the decl's begin location. That is:

SourceMgr.getSpellingLoc(D->getBeginLoc())

Diff Detail

Event Timeline

danakj created this revision.Jan 25 2023, 8:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 25 2023, 8:56 AM
Herald added a subscriber: arphaman. · View Herald Transcript
danakj requested review of this revision.Jan 25 2023, 8:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 25 2023, 8:56 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
danakj updated this revision to Diff 492141.Jan 25 2023, 9:01 AM

Adding back a period that was removed from a comment.

clang/test/Index/annotate-comments-objc.m
121

The comment is no longer attached to the enums generated by NS_ENUM, it is attached to the decl which is found in the text directly after the comment, which is the typedef, only.

danakj updated this revision to Diff 492172.Jan 25 2023, 10:23 AM

Ensure the comment outside the macro is attached to enums defined
inside NS_ENUM() and NS_OPTIONS() macros.

clang/test/Index/annotate-comments-objc.m
121

Restored binding the comment outside the macro to the enums defined inside NS_ENUM() and NS_OPTIONS()

danakj updated this revision to Diff 492176.Jan 25 2023, 10:25 AM

Improve the comment

danakj updated this revision to Diff 492181.Jan 25 2023, 10:43 AM

Add tests for enums inside a macro, other than NS_ENUM and NS_OPTIONS

gribozavr2 accepted this revision.Jan 25 2023, 11:30 AM
This revision is now accepted and ready to land.Jan 25 2023, 11:30 AM
This revision was landed with ongoing or failed builds.Jan 26 2023, 1:13 AM
This revision was automatically updated to reflect the committed changes.
danakj added a comment.EditedJan 26 2023, 11:23 AM

Here's the relevant part of the test:

#define DECLARE_ENUMS(name) \
  /** enumFromMacro IS_DOXYGEN_SINGLE */ \
  enum enumFromMacro { A }; \
  /** namedEnumFromMacro IS_DOXYGEN_SINGLE */ \
  enum name { B };

/// IS_DOXYGEN_NOT_ATTACHED
DECLARE_ENUMS(namedEnumFromMacro)

From the error I see:

  • The Decl is enum namedEnumFromMacro, which has a source location at 74:1, and has a spelling location at 74:15.
DECLARE_ENUMS(namedEnumFromMacro)
^ source      ^ spelling
  • We then call Decl::getBeginLoc(), which doesn't move the source location itself, but does move spelling location.
#define DECLARE_ENUMS(name) \
  /** enumFromMacro IS_DOXYGEN_SINGLE */ \
  enum enumFromMacro { A }; \
  /** namedEnumFromMacro IS_DOXYGEN_SINGLE */ \
  enum name { B };
  ^ spelling

/// IS_DOXYGEN_NOT_ATTACHED
DECLARE_ENUMS(namedEnumFromMacro)
^ source

It seems (from reading the logs) that Decl::getBeginLoc() does not have the correct spelling location in this test, on AIX. It is staying at the original source location at the macro expansion.

danakj added a comment.EditedJan 26 2023, 11:33 AM

I am not sure how to debug further for AIX, do you have any suggestion?

In case it is helpful, I would debug it by adding these at the bottom of the DeclLoc.isMacroID() branch in getDeclLocForCommentSearch() in ASTContext.cpp:

// The location (and spelling location) of the decl.
DeclLoc.dump(SourceMgr);
// The spelling location dumped should move to inside the macro.
D->getBeginLoc().dump(SourceMgr);
danakj added a comment.EditedJan 26 2023, 12:55 PM

I tried modifying the test to pass an AIX target, running on Linux (thanks thakis for the suggestion):

// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-pch -o %t/out.pch -F %S/Inputs/Frameworks %s
// RUN: %clang_cc1 -triple powerpc64-ibm-aix -include-pch %t/out.pch -F %S/Inputs/Frameworks -fsyntax-only %s

However the test passes.

Thank you for looking into the failure. Fortunately the test is passing on the AIX bot now and locally for me - it looks like a clean build fixed it.

bnbarham added inline comments.
clang/test/Index/annotate-comments-objc.m
67–74

What was the original motivation for the PR here? Was it the DECLARE_FUNCTIONS case above?

For this case, personally I would expect that something like:

#define DEFINE_TAG(name) \
  <anytagdecl> name { .... };

/// Comment attached to foo
DEFINE_TAG(foo)

/// Comment attached to bar
DEFINE_TAG(bar)

Is far more common than the test case here. To put another way, the previous

if (const auto *TD = dyn_cast<TagDecl>(D)) {
  // If location of the tag decl is inside a macro, but the spelling of
  // the tag name comes from a macro argument, it looks like a special
  // macro like NS_ENUM is being used to define the tag decl.  In that
  // case, adjust the source location to the expansion loc so that we can
  // attach the comment to the tag decl.
  if (SourceMgr.isMacroArgExpansion(DeclLoc) && TD->isCompleteDefinition())
    return SourceMgr.getExpansionLoc(DeclLoc);
}

Seems more reasonable to me than the hardcoded macro-name check. Even NS_*-wise there's also NS_ERROR_ENUM, NS_TYPED_ENUM, NS_TYPED_EXTENSIBLE_ENUM, NS_CLOSED_ENUM.