Browse Source

Reworked parsing of preprocessed entities.

Fixes macro expansions and translation units processing.
pull/155/merge
triton 12 years ago
parent
commit
e9fd50983a
  1. 175
      src/CppParser/Parser.cpp
  2. 1
      src/CppParser/Parser.h
  3. 178
      src/Parser/Parser.cpp
  4. 2
      src/Parser/Parser.h

175
src/CppParser/Parser.cpp

@ -309,6 +309,9 @@ static clang::SourceLocation GetDeclStartLocation(clang::CompilerInstance* C,
auto startLoc = SM.getExpansionLoc(D->getLocStart()); auto startLoc = SM.getExpansionLoc(D->getLocStart());
auto startOffset = SM.getFileOffset(startLoc); auto startOffset = SM.getFileOffset(startLoc);
if (clang::dyn_cast_or_null<clang::TranslationUnitDecl>(D))
return startLoc;
auto lineNo = SM.getExpansionLineNumber(startLoc); auto lineNo = SM.getExpansionLineNumber(startLoc);
auto lineBeginLoc = SM.translateLineCol(SM.getFileID(startLoc), lineNo, 1); auto lineBeginLoc = SM.translateLineCol(SM.getFileID(startLoc), lineNo, 1);
auto lineBeginOffset = SM.getFileOffset(lineBeginLoc); auto lineBeginOffset = SM.getFileOffset(lineBeginLoc);
@ -1914,98 +1917,16 @@ bool Parser::IsValidDeclaration(const clang::SourceLocation& Loc)
void Parser::WalkAST() void Parser::WalkAST()
{ {
using namespace clang; auto TU = AST->getTranslationUnitDecl();
if (C->hasPreprocessor())
{
Preprocessor& P = C->getPreprocessor();
PreprocessingRecord* PR = P.getPreprocessingRecord();
if (PR)
{
assert(PR && "Expected a valid preprocessing record");
WalkMacros(PR);
}
}
TranslationUnitDecl* TU = AST->getTranslationUnitDecl();
for(auto it = TU->decls_begin(); it != TU->decls_end(); ++it) for(auto it = TU->decls_begin(); it != TU->decls_end(); ++it)
{ {
Decl* D = (*it); clang::Decl* D = (*it);
WalkDeclarationDef(D); WalkDeclarationDef(D);
} }
} }
//-----------------------------------// //-----------------------------------//
void Parser::WalkMacros(clang::PreprocessingRecord* PR)
{
using namespace clang;
Preprocessor& P = C->getPreprocessor();
for(auto it = PR->begin(); it != PR->end(); ++it)
{
const clang::PreprocessedEntity* PE = (*it);
switch(PE->getKind())
{
case clang::PreprocessedEntity::MacroDefinitionKind:
{
auto MD = cast<clang::MacroDefinition>(PE);
if (!IsValidDeclaration(MD->getLocation()))
break;
const IdentifierInfo* II = MD->getName();
assert(II && "Expected valid identifier info");
MacroInfo* MI = P.getMacroInfo((IdentifierInfo*)II);
if (!MI || MI->isBuiltinMacro() || MI->isFunctionLike())
continue;
SourceManager& SM = C->getSourceManager();
const LangOptions &LangOpts = C->getLangOpts();
auto Loc = MI->getDefinitionLoc();
if (!IsValidDeclaration(Loc))
break;
SourceLocation BeginExpr =
Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts);
auto Range = CharSourceRange::getTokenRange(
BeginExpr, MI->getDefinitionEndLoc());
bool Invalid;
StringRef Expression = Lexer::getSourceText(Range, SM, LangOpts,
&Invalid);
if (Invalid || Expression.empty())
break;
auto macro = new MacroDefinition();
macro->OriginalPtr = (void*) MD;
macro->Name = II->getName().trim();
macro->Expression = Expression.trim();
auto M = GetTranslationUnit(BeginExpr);
if( M != nullptr )
M->Macros.push_back(macro);
break;
}
default: break;
}
}
}
//-----------------------------------//
Variable* Parser::WalkVariable(clang::VarDecl *VD) Variable* Parser::WalkVariable(clang::VarDecl *VD)
{ {
using namespace clang; using namespace clang;
@ -2054,6 +1975,8 @@ PreprocessedEntity* Parser::WalkPreprocessedEntity(
return Entity; return Entity;
} }
auto& P = C->getPreprocessor();
PreprocessedEntity* Entity; PreprocessedEntity* Entity;
switch(PPEntity->getKind()) switch(PPEntity->getKind())
@ -2073,19 +1996,68 @@ PreprocessedEntity* Parser::WalkPreprocessedEntity(
case clang::PreprocessedEntity::MacroDefinitionKind: case clang::PreprocessedEntity::MacroDefinitionKind:
{ {
auto MD = cast<clang::MacroDefinition>(PPEntity); auto MD = cast<clang::MacroDefinition>(PPEntity);
Entity = new MacroDefinition();
break; if (!IsValidDeclaration(MD->getLocation()))
break;
const IdentifierInfo* II = MD->getName();
assert(II && "Expected valid identifier info");
MacroInfo* MI = P.getMacroInfo((IdentifierInfo*)II);
if (!MI || MI->isBuiltinMacro() || MI->isFunctionLike())
break;
SourceManager& SM = C->getSourceManager();
const LangOptions &LangOpts = C->getLangOpts();
auto Loc = MI->getDefinitionLoc();
if (!IsValidDeclaration(Loc))
break;
SourceLocation BeginExpr =
Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts);
auto Range = CharSourceRange::getTokenRange(
BeginExpr, MI->getDefinitionEndLoc());
bool Invalid;
StringRef Expression = Lexer::getSourceText(Range, SM, LangOpts,
&Invalid);
if (Invalid || Expression.empty())
break;
auto Definition = new MacroDefinition();
Entity = Definition;
Definition->Name = II->getName().trim();
Definition->Expression = Expression.trim();
} }
default:
return nullptr;
} }
if (!Entity)
return nullptr;
Entity->OriginalPtr = PPEntity; Entity->OriginalPtr = PPEntity;
Decl->PreprocessedEntities.push_back(Entity); Decl->PreprocessedEntities.push_back(Entity);
return Entity; return Entity;
} }
void Parser::HandlePreprocessedEntities(Declaration* Decl)
{
using namespace clang;
auto PPRecord = C->getPreprocessor().getPreprocessingRecord();
for (auto it = PPRecord->begin(); it != PPRecord->end(); ++it)
{
clang::PreprocessedEntity* PPEntity = (*it);
auto Entity = WalkPreprocessedEntity(Decl, PPEntity);
}
}
void Parser::HandlePreprocessedEntities(Declaration* Decl, void Parser::HandlePreprocessedEntities(Declaration* Decl,
clang::SourceRange sourceRange, clang::SourceRange sourceRange,
MacroLocation macroLocation) MacroLocation macroLocation)
@ -2139,13 +2111,20 @@ void Parser::HandleDeclaration(clang::Decl* D, Declaration* Decl)
Decl->OriginalPtr = (void*) D; Decl->OriginalPtr = (void*) D;
if (Decl->PreprocessedEntities.empty()) if (!Decl->PreprocessedEntities.empty())
{ {
auto startLoc = GetDeclStartLocation(C.get(), D); if (clang::dyn_cast<clang::TranslationUnitDecl>(D))
auto endLoc = D->getLocEnd(); {
auto range = clang::SourceRange(startLoc, endLoc); HandlePreprocessedEntities(Decl);
}
else
{
auto startLoc = GetDeclStartLocation(C.get(), D);
auto endLoc = D->getLocEnd();
auto range = clang::SourceRange(startLoc, endLoc);
HandlePreprocessedEntities(Decl, range); HandlePreprocessedEntities(Decl, range);
}
} }
HandleOriginalText(D, Decl); HandleOriginalText(D, Decl);
@ -2481,9 +2460,10 @@ ParserResult* Parser::ParseHeader(const std::string& File)
const clang::DirectoryLookup *Dir; const clang::DirectoryLookup *Dir;
llvm::SmallVector<const clang::FileEntry*, 0> Includers; llvm::SmallVector<const clang::FileEntry*, 0> Includers;
if (!C->getPreprocessor().getHeaderSearchInfo().LookupFile(File, auto FileEntry = C->getPreprocessor().getHeaderSearchInfo().LookupFile(File,
clang::SourceLocation(), /*isAngled*/true, clang::SourceLocation(), /*isAngled*/true,
nullptr, Dir, Includers, nullptr, nullptr, nullptr)) nullptr, Dir, Includers, nullptr, nullptr, nullptr);
if (!FileEntry)
{ {
res->Kind = ParserResultKind::FileNotFound; res->Kind = ParserResultKind::FileNotFound;
return res; return res;
@ -2516,6 +2496,11 @@ ParserResult* Parser::ParseHeader(const std::string& File)
AST = &C->getASTContext(); AST = &C->getASTContext();
auto FileName = FileEntry->getName();
auto Unit = Lib->FindOrCreateModule(FileName);
auto TU = AST->getTranslationUnitDecl();
HandleDeclaration(TU, Unit);
// Initialize enough Clang codegen machinery so we can get at ABI details. // Initialize enough Clang codegen machinery so we can get at ABI details.
llvm::LLVMContext Ctx; llvm::LLVMContext Ctx;
llvm::OwningPtr<llvm::Module> M(new llvm::Module("", Ctx)); llvm::OwningPtr<llvm::Module> M(new llvm::Module("", Ctx));

1
src/CppParser/Parser.h

@ -97,6 +97,7 @@ protected:
std::string GetTypeName(const clang::Type* Type); std::string GetTypeName(const clang::Type* Type);
void WalkFunction(clang::FunctionDecl* FD, Function* F, void WalkFunction(clang::FunctionDecl* FD, Function* F,
bool IsDependent = false); bool IsDependent = false);
void HandlePreprocessedEntities(Declaration* Decl);
void HandlePreprocessedEntities(Declaration* Decl, clang::SourceRange sourceRange, void HandlePreprocessedEntities(Declaration* Decl, clang::SourceRange sourceRange,
MacroLocation macroLocation = MacroLocation::Unknown); MacroLocation macroLocation = MacroLocation::Unknown);
bool GetDeclText(clang::SourceRange SR, std::string& Text); bool GetDeclText(clang::SourceRange SR, std::string& Text);

178
src/Parser/Parser.cpp

@ -309,6 +309,9 @@ static clang::SourceLocation GetDeclStartLocation(clang::CompilerInstance* C,
auto startLoc = SM.getExpansionLoc(D->getLocStart()); auto startLoc = SM.getExpansionLoc(D->getLocStart());
auto startOffset = SM.getFileOffset(startLoc); auto startOffset = SM.getFileOffset(startLoc);
if (clang::dyn_cast_or_null<clang::TranslationUnitDecl>(D))
return startLoc;
auto lineNo = SM.getExpansionLineNumber(startLoc); auto lineNo = SM.getExpansionLineNumber(startLoc);
auto lineBeginLoc = SM.translateLineCol(SM.getFileID(startLoc), lineNo, 1); auto lineBeginLoc = SM.translateLineCol(SM.getFileID(startLoc), lineNo, 1);
auto lineBeginOffset = SM.getFileOffset(lineBeginLoc); auto lineBeginOffset = SM.getFileOffset(lineBeginLoc);
@ -1936,99 +1939,16 @@ bool Parser::IsValidDeclaration(const clang::SourceLocation& Loc)
void Parser::WalkAST() void Parser::WalkAST()
{ {
using namespace clang; auto TU = AST->getTranslationUnitDecl();
if (C->hasPreprocessor())
{
Preprocessor& P = C->getPreprocessor();
PreprocessingRecord* PR = P.getPreprocessingRecord();
if (PR)
{
assert(PR && "Expected a valid preprocessing record");
WalkMacros(PR);
}
}
TranslationUnitDecl* TU = AST->getTranslationUnitDecl();
for(auto it = TU->decls_begin(); it != TU->decls_end(); ++it) for(auto it = TU->decls_begin(); it != TU->decls_end(); ++it)
{ {
Decl* D = (*it); clang::Decl* D = (*it);
WalkDeclarationDef(D); WalkDeclarationDef(D);
} }
} }
//-----------------------------------// //-----------------------------------//
void Parser::WalkMacros(clang::PreprocessingRecord* PR)
{
using namespace clang;
using namespace clix;
Preprocessor& P = C->getPreprocessor();
for(auto it = PR->begin(); it != PR->end(); ++it)
{
const PreprocessedEntity* PE = (*it);
switch(PE->getKind())
{
case PreprocessedEntity::MacroDefinitionKind:
{
auto MD = cast<MacroDefinition>(PE);
if (!IsValidDeclaration(MD->getLocation()))
break;
const IdentifierInfo* II = MD->getName();
assert(II && "Expected valid identifier info");
MacroInfo* MI = P.getMacroInfo((IdentifierInfo*)II);
if (!MI || MI->isBuiltinMacro() || MI->isFunctionLike())
continue;
SourceManager& SM = C->getSourceManager();
const LangOptions &LangOpts = C->getLangOpts();
auto Loc = MI->getDefinitionLoc();
if (!IsValidDeclaration(Loc))
break;
SourceLocation BeginExpr =
Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts);
auto Range = CharSourceRange::getTokenRange(
BeginExpr, MI->getDefinitionEndLoc());
bool Invalid;
StringRef Expression = Lexer::getSourceText(Range, SM, LangOpts,
&Invalid);
if (Invalid || Expression.empty())
break;
auto macro = gcnew CppSharp::AST::MacroDefinition();
macro->OriginalPtr = System::IntPtr((void*)MD);
macro->Name = marshalString<E_UTF8>(II->getName())->Trim();
macro->Expression = marshalString<E_UTF8>(Expression)->Trim();
auto M = GetTranslationUnit(BeginExpr);
if( M != nullptr )
M->Macros->Add(macro);
break;
}
default: break;
}
}
}
//-----------------------------------//
CppSharp::AST::Variable^ Parser::WalkVariable(clang::VarDecl *VD) CppSharp::AST::Variable^ Parser::WalkVariable(clang::VarDecl *VD)
{ {
using namespace clang; using namespace clang;
@ -2078,13 +1998,15 @@ CppSharp::AST::PreprocessedEntity^ Parser::WalkPreprocessedEntity(
return Entity; return Entity;
} }
auto& P = C->getPreprocessor();
CppSharp::AST::PreprocessedEntity^ Entity; CppSharp::AST::PreprocessedEntity^ Entity;
switch(PPEntity->getKind()) switch(PPEntity->getKind())
{ {
case PreprocessedEntity::MacroExpansionKind: case PreprocessedEntity::MacroExpansionKind:
{ {
const MacroExpansion* MD = cast<MacroExpansion>(PPEntity); auto MD = cast<MacroExpansion>(PPEntity);
Entity = gcnew CppSharp::AST::MacroExpansion(); Entity = gcnew CppSharp::AST::MacroExpansion();
std::string Text; std::string Text;
@ -2097,20 +2019,69 @@ CppSharp::AST::PreprocessedEntity^ Parser::WalkPreprocessedEntity(
} }
case PreprocessedEntity::MacroDefinitionKind: case PreprocessedEntity::MacroDefinitionKind:
{ {
const MacroDefinition* MD = cast<MacroDefinition>(PPEntity); auto MD = cast<MacroDefinition>(PPEntity);
Entity = gcnew CppSharp::AST::MacroDefinition();
break; if (!IsValidDeclaration(MD->getLocation()))
break;
const IdentifierInfo* II = MD->getName();
assert(II && "Expected valid identifier info");
MacroInfo* MI = P.getMacroInfo((IdentifierInfo*)II);
if (!MI || MI->isBuiltinMacro() || MI->isFunctionLike())
break;
SourceManager& SM = C->getSourceManager();
const LangOptions &LangOpts = C->getLangOpts();
auto Loc = MI->getDefinitionLoc();
if (!IsValidDeclaration(Loc))
break;
SourceLocation BeginExpr =
Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts);
auto Range = CharSourceRange::getTokenRange(
BeginExpr, MI->getDefinitionEndLoc());
bool Invalid;
StringRef Expression = Lexer::getSourceText(Range, SM, LangOpts,
&Invalid);
if (Invalid || Expression.empty())
break;
auto Definition = gcnew CppSharp::AST::MacroDefinition();
Entity = Definition;
Definition->Name = clix::marshalString<clix::E_UTF8>(II->getName())->Trim();
Definition->Expression = clix::marshalString<clix::E_UTF8>(Expression)->Trim();
} }
default:
return nullptr;
} }
if (!Entity)
return nullptr;
Entity->OriginalPtr = System::IntPtr(PPEntity); Entity->OriginalPtr = System::IntPtr(PPEntity);
Decl->PreprocessedEntities->Add(Entity); Decl->PreprocessedEntities->Add(Entity);
return Entity; return Entity;
} }
void Parser::HandlePreprocessedEntities(CppSharp::AST::Declaration^ Decl)
{
using namespace clang;
auto PPRecord = C->getPreprocessor().getPreprocessingRecord();
for (auto it = PPRecord->begin(); it != PPRecord->end(); ++it)
{
PreprocessedEntity* PPEntity = (*it);
auto Entity = WalkPreprocessedEntity(Decl, PPEntity);
}
}
void Parser::HandlePreprocessedEntities(CppSharp::AST::Declaration^ Decl, void Parser::HandlePreprocessedEntities(CppSharp::AST::Declaration^ Decl,
clang::SourceRange sourceRange, clang::SourceRange sourceRange,
CppSharp::AST::MacroLocation macroLocation) CppSharp::AST::MacroLocation macroLocation)
@ -2166,11 +2137,18 @@ void Parser::HandleDeclaration(clang::Decl* D, CppSharp::AST::Declaration^ Decl)
if (Decl->PreprocessedEntities->Count == 0) if (Decl->PreprocessedEntities->Count == 0)
{ {
auto startLoc = GetDeclStartLocation(C.get(), D); if (clang::dyn_cast<clang::TranslationUnitDecl>(D))
auto endLoc = D->getLocEnd(); {
auto range = clang::SourceRange(startLoc, endLoc); HandlePreprocessedEntities(Decl);
}
else
{
auto startLoc = GetDeclStartLocation(C.get(), D);
auto endLoc = D->getLocEnd();
auto range = clang::SourceRange(startLoc, endLoc);
HandlePreprocessedEntities(Decl, range); HandlePreprocessedEntities(Decl, range);
}
} }
HandleOriginalText(D, Decl); HandleOriginalText(D, Decl);
@ -2496,9 +2474,10 @@ ParserResult^ Parser::ParseHeader(const std::string& File)
const clang::DirectoryLookup *Dir; const clang::DirectoryLookup *Dir;
llvm::SmallVector<const clang::FileEntry*, 0> Includers; llvm::SmallVector<const clang::FileEntry*, 0> Includers;
if (!C->getPreprocessor().getHeaderSearchInfo().LookupFile(File, auto FileEntry = C->getPreprocessor().getHeaderSearchInfo().LookupFile(File,
clang::SourceLocation(), /*isAngled*/true, clang::SourceLocation(), /*isAngled*/true,
nullptr, Dir, Includers, nullptr, nullptr, nullptr)) nullptr, Dir, Includers, nullptr, nullptr, nullptr);
if (!FileEntry)
{ {
res->Kind = ParserResultKind::FileNotFound; res->Kind = ParserResultKind::FileNotFound;
return res; return res;
@ -2531,6 +2510,11 @@ ParserResult^ Parser::ParseHeader(const std::string& File)
AST = &C->getASTContext(); AST = &C->getASTContext();
auto FileName = clix::marshalString<clix::E_UTF8>(FileEntry->getName());
auto Unit = Lib->FindOrCreateModule(FileName);
auto TU = AST->getTranslationUnitDecl();
HandleDeclaration(TU, Unit);
// Initialize enough Clang codegen machinery so we can get at ABI details. // Initialize enough Clang codegen machinery so we can get at ABI details.
llvm::LLVMContext Ctx; llvm::LLVMContext Ctx;
llvm::OwningPtr<llvm::Module> M(new llvm::Module("", Ctx)); llvm::OwningPtr<llvm::Module> M(new llvm::Module("", Ctx));

2
src/Parser/Parser.h

@ -59,7 +59,6 @@ protected:
// AST traversers // AST traversers
void WalkAST(); void WalkAST();
void WalkMacros(clang::PreprocessingRecord* PR);
CppSharp::AST::Declaration^ WalkDeclaration(clang::Decl* D, CppSharp::AST::Declaration^ WalkDeclaration(clang::Decl* D,
bool IgnoreSystemDecls = true, bool CanBeDefinition = false); bool IgnoreSystemDecls = true, bool CanBeDefinition = false);
CppSharp::AST::Declaration^ WalkDeclarationDef(clang::Decl* D); CppSharp::AST::Declaration^ WalkDeclarationDef(clang::Decl* D);
@ -96,6 +95,7 @@ protected:
std::string GetTypeName(const clang::Type* Type); std::string GetTypeName(const clang::Type* Type);
void WalkFunction(clang::FunctionDecl* FD, CppSharp::AST::Function^ F, void WalkFunction(clang::FunctionDecl* FD, CppSharp::AST::Function^ F,
bool IsDependent = false); bool IsDependent = false);
void HandlePreprocessedEntities(CppSharp::AST::Declaration^ Decl);
void HandlePreprocessedEntities(CppSharp::AST::Declaration^ Decl, clang::SourceRange sourceRange, void HandlePreprocessedEntities(CppSharp::AST::Declaration^ Decl, clang::SourceRange sourceRange,
CppSharp::AST::MacroLocation macroLocation = CppSharp::AST::MacroLocation::Unknown); CppSharp::AST::MacroLocation macroLocation = CppSharp::AST::MacroLocation::Unknown);
bool GetDeclText(clang::SourceRange SR, std::string& Text); bool GetDeclText(clang::SourceRange SR, std::string& Text);

Loading…
Cancel
Save