SourceManager.getFilename() fails to return the name of header file

Hello list,

I am writing a tool to analyze C/C++ code written for a compiler for
MCUs (e.g. a compiler from IAR Systems, Windriver, Cosmic, Keil)

To create the input file for my analyzer I have to use the compilers
preprocessor to handle the compiler specific command line options. The
result of this step is an output file like this.

# 1 "T://source.c"
# 1 "D:\\Program_Files_32\\Windriver\\diab\\5.9.4.2\\include\\math.h" 1
# 1 "D:\\Program_Files_32\\Windriver\\diab\\5.9.4.2\\include\\xmacros.h" 1
# 1
"D:\\Program_Files_32\\Windriver\\diab\\5.9.4.2\\include\\diab/xmacros.h" 1
.
.
# 4 "D:\\Program_Files_32\\Windriver\\diab\\5.9.4.2\\include\\xmacros.h" 1
# 4 "D:\\Program_Files_32\\Windriver\\diab\\5.9.4.2\\include\\math.h" 1
.
.
extern long double double cosl_not_supported(void);

inline long double cosl(long double)
  {
  return ( long_double_cosl_not_supported() );
  }
.
.
# 3 "T://source.c"

int foo () {
  return 1;
}

Inside my AST visitor if have a function like this that gets a FunctionDecl:

void handleFunctionDecl (const * FunctionDecl) {
}

To check if the declaration is inside a system header I use the
following code which works as expected:

ASTContext & context(decl->getASTContext());
FullSourceLoc location(context.getFullLoc(decl->getLocStart()));
bool in_system_header(false);

if (location.isValid()) {
   in_system_header = location.isInSystemHeader();
}

I also want to know the header file from wich the declaration comes and
tried the following:

ASTContext & context(decl->getASTContext());
SourceManager & manager(context.getSourceManager());
SourceLocation location(decl->getLocStart());

But `manager.getFilename(location)` always returns the name of the main
file.

So I want to ask if I am missing something in setting up the `ClangTool`
that I am using to produce the ast? Or is there a trick to teach the
SourceManager to return the name of the header file.

Here are the (simplified) steps to create the asts for analysis:

vector<unique_ptr<ASTUnit>> asts;
CommonOptionsParser options_parser(...);
ClangTool * tool = new ClangTool(..);
IntrusiveRefCntPtr<DiagnosticOptions> options = new DiagnosticOptions();
ToolDiagnosticConsumer * consumer = new
ToolDiagnosticConsumer(&*options);

tool->setDiagnosticConsumer(consumer);
int result = tool->buildASTs(asts);

Thanks

Frank

I’d recommend using http://clang.llvm.org/docs/LibTooling.html instead of running on the preprocessed code.

I think that you should be able to get the presumed filename by using SourceManager::getPresumedLoc, e.g.:

PresumedLoc PLoc = manager.getPresumedLoc(location);

if (PLoc.isValid()) {
Filename = PLoc.getFilename();
}

I think that you should be able to get the presumed filename by using
`SourceManager::getPresumedLoc`, e.g.:

PresumedLoc PLoc = manager.getPresumedLoc(location);
if (PLoc.isValid()) {
  Filename = PLoc.getFilename();
}

Many thanks Alex, works great for me!

Frank