Distinguishing system headers from user headers using libclang

Hi,

I’m writing a simple code dependency analysis tool using libclang and I’m missing some way of distinguishing system headers from user headers. I see clang::DirectoryLookup::getDirCharacteristic() provides such interface, but is there any way I could obtain this information using just libclang? My tool is rather simple and I’d like to keep it that way - libclang seems to be sufficient for the rest of my needs.

Thanks,

Hi,

I’m writing a simple code dependency analysis tool using libclang and I’m missing some way of distinguishing system headers from user headers. I see clang::DirectoryLookup::getDirCharacteristic() provides such interface, but is there any way I could obtain this information using just libclang? My tool is rather simple and I’d like to keep it that way - libclang seems to be sufficient for the rest of my needs.

There is no way currently, but it should relatively easy, are you interested in providing such a patch ?
The clang function you may need to look into using is “SourceManager::isInSystemHeader(SourceLocation Loc)”
The libclang function would accept a CXTranslationUnit and a CXSourceLocation.

How about this? That's the best and most elastic approach I could think of.

file-characteristics.diff (2.89 KB)

There was unnecessary CINDEX_LINKAGE in the first version of my patch.
Here's corrected one.

file-characteristics-v2.diff (2.87 KB)

Hi,

I’m writing a simple code dependency analysis tool using libclang and I’m missing some way of distinguishing system headers from user headers. I see clang::DirectoryLookup::getDirCharacteristic() provides such interface, but is there any way I could obtain this information using just libclang? My tool is rather simple and I’d like to keep it that way - libclang seems to be sufficient for the rest of my needs.

There is no way currently, but it should relatively easy, are you interested in providing such a patch ?
The clang function you may need to look into using is “SourceManager::isInSystemHeader(SourceLocation Loc)”
The libclang function would accept a CXTranslationUnit and a CXSourceLocation.

How about this? That’s the best and most elastic approach I could think of.

There was unnecessary CINDEX_LINKAGE in the first version of my patch.
Here’s corrected one.

  • /**
    • \brief System code which is implicitly ‘extern “C”’ in C++ mode
  • */
  • CXCharacteristicKind_ExternCSystem

This is very “legacy-hacky-compiler-specific”; I can’t think of a reason that a libclang client would need to know this.

I suggest just adding a
int clang_SourceLocation_isInSystemHeader(CXSourceLocation location)
function.

I agree ExternCSystem may not be useful - I added it to mimic
underlaying library interface. Nevertheless, I don't think boolean
isInSystemHeader is enough. For example - in my program I need to know
whether given source location is in user code. !isInSystemHeader
wouldn't be enough, because there are also invalid locations like
built-in compiler declarations or anything really that has no
corresponding location in the source.

Hi,

I'm writing a simple code dependency analysis tool using libclang and I'm
missing some way of distinguishing system headers from user headers. I see
clang::DirectoryLookup::getDirCharacteristic() provides such interface, but
is there any way I could obtain this information using just libclang? My
tool is rather simple and I'd like to keep it that way - libclang seems to
be sufficient for the rest of my needs.

There is no way currently, but it should relatively easy, are you interested
in providing such a patch ?
The clang function you may need to look into using is
"SourceManager::isInSystemHeader(SourceLocation Loc)"
The libclang function would accept a CXTranslationUnit and a
CXSourceLocation.

How about this? That's the best and most elastic approach I could think of.

There was unnecessary CINDEX_LINKAGE in the first version of my patch.
Here's corrected one.

+ /**
+ * \brief System code which is implicitly 'extern "C"' in C++ mode
+ */
+ CXCharacteristicKind_ExternCSystem

This is very "legacy-hacky-compiler-specific"; I can't think of a reason
that a libclang client would need to know this.

I suggest just adding a
int clang_SourceLocation_isInSystemHeader(CXSourceLocation location)
function.

I agree ExternCSystem may not be useful - I added it to mimic
underlaying library interface. Nevertheless, I don't think boolean
isInSystemHeader is enough. For example - in my program I need to know
whether given source location is in user code. !isInSystemHeader
wouldn't be enough, because there are also invalid locations like
built-in compiler declarations or anything really that has no
corresponding location in the source.

To check for invalid locations you can do:
if (clang_equalLocations(Location, clang_getNullLocation()) {
  // invalid
}

I don't really think that's user/client-friendly approach to have a
combination of
different interface functions providing same information type, but I guess it's
your choice. Here's simple isInSystemHeader.

file-characteristics-v3.diff (1.77 KB)

Hi,

I’m writing a simple code dependency analysis tool using libclang and I’m
missing some way of distinguishing system headers from user headers. I see
clang::DirectoryLookup::getDirCharacteristic() provides such interface, but
is there any way I could obtain this information using just libclang? My
tool is rather simple and I’d like to keep it that way - libclang seems to
be sufficient for the rest of my needs.

There is no way currently, but it should relatively easy, are you interested
in providing such a patch ?
The clang function you may need to look into using is
“SourceManager::isInSystemHeader(SourceLocation Loc)”
The libclang function would accept a CXTranslationUnit and a
CXSourceLocation.

How about this? That’s the best and most elastic approach I could think of.

There was unnecessary CINDEX_LINKAGE in the first version of my patch.
Here’s corrected one.

  • /**
    • \brief System code which is implicitly ‘extern “C”’ in C++ mode
  • */
  • CXCharacteristicKind_ExternCSystem

This is very “legacy-hacky-compiler-specific”; I can’t think of a reason
that a libclang client would need to know this.

I suggest just adding a
int clang_SourceLocation_isInSystemHeader(CXSourceLocation location)
function.

I agree ExternCSystem may not be useful - I added it to mimic
underlaying library interface. Nevertheless, I don’t think boolean
isInSystemHeader is enough. For example - in my program I need to know
whether given source location is in user code. !isInSystemHeader
wouldn’t be enough, because there are also invalid locations like
built-in compiler declarations or anything really that has no
corresponding location in the source.

To check for invalid locations you can do:
if (clang_equalLocations(Location, clang_getNullLocation()) {
// invalid
}

I don’t really think that’s user/client-friendly approach to have a
combination of
different interface functions providing same information type, but I guess it’s
your choice.

In general there are libclang functions to determine if an object is null/invalid and more functions to query information from the object. If all clang_is* functions were changed to return an enum to also cover the null/invalid case, this would be rather user unfriendly.

Here’s simple isInSystemHeader.

Committed a modified patch in r179384, thanks!