diff --git a/src/Bridge/Preprocessor.cs b/src/Bridge/Preprocessor.cs
index 1b20418d..177a9ce0 100644
--- a/src/Bridge/Preprocessor.cs
+++ b/src/Bridge/Preprocessor.cs
@@ -1,12 +1,22 @@
namespace CppSharp
{
+ public enum MacroLocation
+ {
+ Unknown,
+ ClassHead,
+ ClassBody,
+ FunctionHead,
+ FunctionParameters,
+ FunctionBody,
+ };
+
///
/// Base class that describes a preprocessed entity, which may
/// be a preprocessor directive or macro expansion.
///
public abstract class PreprocessedEntity : Declaration
{
-
+ public MacroLocation Location = MacroLocation.Unknown;
}
///
diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp
index 850dedd2..7539b977 100644
--- a/src/Parser/Parser.cpp
+++ b/src/Parser/Parser.cpp
@@ -262,6 +262,56 @@ static std::string GetTagDeclName(const clang::TagDecl* D)
return GetDeclName(D);
}
+static clang::Decl* GetPreviousDeclInContext(const clang::Decl* D)
+{
+ assert(!D->getLexicalDeclContext()->decls_empty());
+
+ clang::Decl* prevDecl = nullptr;
+ for(auto it = D->getDeclContext()->decls_begin();
+ it != D->getDeclContext()->decls_end(); it++)
+ {
+ if((*it) == D)
+ return prevDecl;
+ prevDecl = (*it);
+ }
+
+ return nullptr;
+}
+
+static clang::SourceLocation GetDeclStartLocation(clang::CompilerInstance* C,
+ const clang::Decl* D)
+{
+ auto &SM = C->getSourceManager();
+ auto startLoc = SM.getExpansionLoc(D->getLocStart());
+ auto startOffset = SM.getFileOffset(startLoc);
+
+ auto lineNo = SM.getExpansionLineNumber(startLoc);
+ auto lineBeginLoc = SM.translateLineCol(SM.getFileID(startLoc), lineNo, 1);
+ auto lineBeginOffset = SM.getFileOffset(lineBeginLoc);
+ assert(lineBeginOffset <= startOffset);
+
+ auto prevDecl = GetPreviousDeclInContext(D);
+ if(!prevDecl)
+ return lineBeginLoc;
+
+ auto prevDeclEndLoc = SM.getExpansionLoc(prevDecl->getLocEnd());
+ auto prevDeclEndOffset = SM.getFileOffset(prevDeclEndLoc);
+
+ if(SM.getFileID(prevDeclEndLoc) != SM.getFileID(startLoc))
+ return lineBeginLoc;
+
+ assert(prevDeclEndOffset <= startOffset);
+
+ if(prevDeclEndOffset < lineBeginOffset)
+ return lineBeginLoc;
+
+ // Declarations don't share same macro expansion
+ if(SM.getExpansionLoc(prevDecl->getLocStart()) != startLoc)
+ return prevDeclEndLoc;
+
+ return GetDeclStartLocation(C, prevDecl);
+}
+
std::string Parser::GetTypeName(const clang::Type* Type)
{
using namespace clang;
@@ -341,7 +391,15 @@ CppSharp::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record)
if (!isCompleteDefinition)
return RC;
- HandlePreprocessedEntities(Record, RC);
+ auto headStartLoc = GetDeclStartLocation(C.get(), Record);
+ auto headEndLoc = Record->getLocation(); // identifier location
+ auto bodyEndLoc = Record->getLocEnd();
+
+ auto headRange = clang::SourceRange(headStartLoc, headEndLoc);
+ auto bodyRange = clang::SourceRange(headEndLoc, bodyEndLoc);
+
+ HandlePreprocessedEntities(RC, headRange, CppSharp::MacroLocation::ClassHead);
+ HandlePreprocessedEntities(RC, bodyRange, CppSharp::MacroLocation::ClassBody);
RC->IsPOD = Record->isPOD();
RC->IsUnion = Record->isUnion();
@@ -1205,10 +1263,20 @@ void Parser::WalkFunction(clang::FunctionDecl* FD, CppSharp::Function^ F,
TypeLoc RTL;
if (auto TSI = FD->getTypeSourceInfo())
{
- TypeLoc TL = TSI->getTypeLoc();
- //RTL = ResolveTypeLoc(TL).getAs.getResultLoc();
- RTL = TL.getAs().getResultLoc();
+ FunctionTypeLoc FTL = TSI->getTypeLoc().getAs();
+ RTL = FTL.getResultLoc();
+
+ auto &SM = C->getSourceManager();
+ auto headStartLoc = GetDeclStartLocation(C.get(), FD);
+ auto headEndLoc = SM.getExpansionLoc(FTL.getLParenLoc());
+ auto headRange = clang::SourceRange(headStartLoc, headEndLoc);
+
+ HandlePreprocessedEntities(F, headRange, CppSharp::MacroLocation::FunctionHead);
+ HandlePreprocessedEntities(F, FTL.getParensRange(), CppSharp::MacroLocation::FunctionParameters);
+ //auto bodyRange = clang::SourceRange(FTL.getRParenLoc(), FD->getLocEnd());
+ //HandlePreprocessedEntities(F, bodyRange, CppSharp::MacroLocation::FunctionBody);
}
+
F->ReturnType = GetQualifiedType(FD->getResultType(),
WalkType(FD->getResultType(), &RTL));
@@ -1448,18 +1516,19 @@ bool Parser::GetPreprocessedEntityText(clang::PreprocessedEntity* PE, std::strin
return !Invalid && !Text.empty();
}
-void Parser::HandlePreprocessedEntities(clang::Decl* D, CppSharp::Declaration^ Decl)
+void Parser::HandlePreprocessedEntities(CppSharp::Declaration^ Decl,
+ clang::SourceRange sourceRange,
+ CppSharp::MacroLocation macroLocation)
{
using namespace clang;
auto PPRecord = C->getPreprocessor().getPreprocessingRecord();
- auto SourceRange = D->getSourceRange();
- auto Range = PPRecord->getPreprocessedEntitiesInRange(SourceRange);
+ auto Range = PPRecord->getPreprocessedEntitiesInRange(sourceRange);
for (auto it = Range.first; it != Range.second; ++it)
{
PreprocessedEntity* PPEntity = (*it);
-
+
CppSharp::PreprocessedEntity^ Entity;
switch(PPEntity->getKind())
{
@@ -1483,9 +1552,11 @@ void Parser::HandlePreprocessedEntities(clang::Decl* D, CppSharp::Declaration^ D
break;
}
default:
- break;
+ continue;
}
+ Entity->Location = macroLocation;
+
Decl->PreprocessedEntities->Add(Entity);
}
}
diff --git a/src/Parser/Parser.h b/src/Parser/Parser.h
index d5fb0e23..8510a3c6 100644
--- a/src/Parser/Parser.h
+++ b/src/Parser/Parser.h
@@ -156,7 +156,8 @@ protected:
void HandleComments(clang::Decl* D, CppSharp::Declaration^);
void WalkFunction(clang::FunctionDecl* FD, CppSharp::Function^ F,
bool IsDependent = false);
- void HandlePreprocessedEntities(clang::Decl* D, CppSharp::Declaration^);
+ void HandlePreprocessedEntities(CppSharp::Declaration^ Decl, clang::SourceRange sourceRange,
+ CppSharp::MacroLocation macroLocation = CppSharp::MacroLocation::Unknown);
bool GetPreprocessedEntityText(clang::PreprocessedEntity*, std::string& Text);
CppSharp::TranslationUnit^ GetTranslationUnit(clang::SourceLocation Loc,