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, @@ -309,6 +309,9 @@ static clang::SourceLocation GetDeclStartLocation(clang::CompilerInstance* C,
auto startLoc = SM.getExpansionLoc(D->getLocStart());
auto startOffset = SM.getFileOffset(startLoc);
if (clang::dyn_cast_or_null<clang::TranslationUnitDecl>(D))
return startLoc;
auto lineNo = SM.getExpansionLineNumber(startLoc);
auto lineBeginLoc = SM.translateLineCol(SM.getFileID(startLoc), lineNo, 1);
auto lineBeginOffset = SM.getFileOffset(lineBeginLoc);
@ -1914,98 +1917,16 @@ bool Parser::IsValidDeclaration(const clang::SourceLocation& Loc) @@ -1914,98 +1917,16 @@ bool Parser::IsValidDeclaration(const clang::SourceLocation& Loc)
void Parser::WalkAST()
{
using namespace clang;
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();
auto TU = AST->getTranslationUnitDecl();
for(auto it = TU->decls_begin(); it != TU->decls_end(); ++it)
{
Decl* D = (*it);
clang::Decl* D = (*it);
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)
{
using namespace clang;
@ -2054,6 +1975,8 @@ PreprocessedEntity* Parser::WalkPreprocessedEntity( @@ -2054,6 +1975,8 @@ PreprocessedEntity* Parser::WalkPreprocessedEntity(
return Entity;
}
auto& P = C->getPreprocessor();
PreprocessedEntity* Entity;
switch(PPEntity->getKind())
@ -2073,19 +1996,68 @@ PreprocessedEntity* Parser::WalkPreprocessedEntity( @@ -2073,19 +1996,68 @@ PreprocessedEntity* Parser::WalkPreprocessedEntity(
case clang::PreprocessedEntity::MacroDefinitionKind:
{
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;
Decl->PreprocessedEntities.push_back(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,
clang::SourceRange sourceRange,
MacroLocation macroLocation)
@ -2139,13 +2111,20 @@ void Parser::HandleDeclaration(clang::Decl* D, Declaration* Decl) @@ -2139,13 +2111,20 @@ void Parser::HandleDeclaration(clang::Decl* D, Declaration* Decl)
Decl->OriginalPtr = (void*) D;
if (Decl->PreprocessedEntities.empty())
if (!Decl->PreprocessedEntities.empty())
{
auto startLoc = GetDeclStartLocation(C.get(), D);
auto endLoc = D->getLocEnd();
auto range = clang::SourceRange(startLoc, endLoc);
if (clang::dyn_cast<clang::TranslationUnitDecl>(D))
{
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);
@ -2481,9 +2460,10 @@ ParserResult* Parser::ParseHeader(const std::string& File) @@ -2481,9 +2460,10 @@ ParserResult* Parser::ParseHeader(const std::string& File)
const clang::DirectoryLookup *Dir;
llvm::SmallVector<const clang::FileEntry*, 0> Includers;
if (!C->getPreprocessor().getHeaderSearchInfo().LookupFile(File,
auto FileEntry = C->getPreprocessor().getHeaderSearchInfo().LookupFile(File,
clang::SourceLocation(), /*isAngled*/true,
nullptr, Dir, Includers, nullptr, nullptr, nullptr))
nullptr, Dir, Includers, nullptr, nullptr, nullptr);
if (!FileEntry)
{
res->Kind = ParserResultKind::FileNotFound;
return res;
@ -2516,6 +2496,11 @@ ParserResult* Parser::ParseHeader(const std::string& File) @@ -2516,6 +2496,11 @@ ParserResult* Parser::ParseHeader(const std::string& File)
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.
llvm::LLVMContext Ctx;
llvm::OwningPtr<llvm::Module> M(new llvm::Module("", Ctx));

1
src/CppParser/Parser.h

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

178
src/Parser/Parser.cpp

@ -309,6 +309,9 @@ static clang::SourceLocation GetDeclStartLocation(clang::CompilerInstance* C, @@ -309,6 +309,9 @@ static clang::SourceLocation GetDeclStartLocation(clang::CompilerInstance* C,
auto startLoc = SM.getExpansionLoc(D->getLocStart());
auto startOffset = SM.getFileOffset(startLoc);
if (clang::dyn_cast_or_null<clang::TranslationUnitDecl>(D))
return startLoc;
auto lineNo = SM.getExpansionLineNumber(startLoc);
auto lineBeginLoc = SM.translateLineCol(SM.getFileID(startLoc), lineNo, 1);
auto lineBeginOffset = SM.getFileOffset(lineBeginLoc);
@ -1936,99 +1939,16 @@ bool Parser::IsValidDeclaration(const clang::SourceLocation& Loc) @@ -1936,99 +1939,16 @@ bool Parser::IsValidDeclaration(const clang::SourceLocation& Loc)
void Parser::WalkAST()
{
using namespace clang;
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();
auto TU = AST->getTranslationUnitDecl();
for(auto it = TU->decls_begin(); it != TU->decls_end(); ++it)
{
Decl* D = (*it);
clang::Decl* D = (*it);
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)
{
using namespace clang;
@ -2078,13 +1998,15 @@ CppSharp::AST::PreprocessedEntity^ Parser::WalkPreprocessedEntity( @@ -2078,13 +1998,15 @@ CppSharp::AST::PreprocessedEntity^ Parser::WalkPreprocessedEntity(
return Entity;
}
auto& P = C->getPreprocessor();
CppSharp::AST::PreprocessedEntity^ Entity;
switch(PPEntity->getKind())
{
case PreprocessedEntity::MacroExpansionKind:
{
const MacroExpansion* MD = cast<MacroExpansion>(PPEntity);
auto MD = cast<MacroExpansion>(PPEntity);
Entity = gcnew CppSharp::AST::MacroExpansion();
std::string Text;
@ -2097,20 +2019,69 @@ CppSharp::AST::PreprocessedEntity^ Parser::WalkPreprocessedEntity( @@ -2097,20 +2019,69 @@ CppSharp::AST::PreprocessedEntity^ Parser::WalkPreprocessedEntity(
}
case PreprocessedEntity::MacroDefinitionKind:
{
const MacroDefinition* MD = cast<MacroDefinition>(PPEntity);
Entity = gcnew CppSharp::AST::MacroDefinition();
break;
auto MD = cast<MacroDefinition>(PPEntity);
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);
Decl->PreprocessedEntities->Add(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,
clang::SourceRange sourceRange,
CppSharp::AST::MacroLocation macroLocation)
@ -2166,11 +2137,18 @@ void Parser::HandleDeclaration(clang::Decl* D, CppSharp::AST::Declaration^ Decl) @@ -2166,11 +2137,18 @@ void Parser::HandleDeclaration(clang::Decl* D, CppSharp::AST::Declaration^ Decl)
if (Decl->PreprocessedEntities->Count == 0)
{
auto startLoc = GetDeclStartLocation(C.get(), D);
auto endLoc = D->getLocEnd();
auto range = clang::SourceRange(startLoc, endLoc);
if (clang::dyn_cast<clang::TranslationUnitDecl>(D))
{
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);
@ -2496,9 +2474,10 @@ ParserResult^ Parser::ParseHeader(const std::string& File) @@ -2496,9 +2474,10 @@ ParserResult^ Parser::ParseHeader(const std::string& File)
const clang::DirectoryLookup *Dir;
llvm::SmallVector<const clang::FileEntry*, 0> Includers;
if (!C->getPreprocessor().getHeaderSearchInfo().LookupFile(File,
auto FileEntry = C->getPreprocessor().getHeaderSearchInfo().LookupFile(File,
clang::SourceLocation(), /*isAngled*/true,
nullptr, Dir, Includers, nullptr, nullptr, nullptr))
nullptr, Dir, Includers, nullptr, nullptr, nullptr);
if (!FileEntry)
{
res->Kind = ParserResultKind::FileNotFound;
return res;
@ -2531,6 +2510,11 @@ ParserResult^ Parser::ParseHeader(const std::string& File) @@ -2531,6 +2510,11 @@ ParserResult^ Parser::ParseHeader(const std::string& File)
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.
llvm::LLVMContext Ctx;
llvm::OwningPtr<llvm::Module> M(new llvm::Module("", Ctx));

2
src/Parser/Parser.h

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

Loading…
Cancel
Save