From e9fd50983a4db9c27ea72101286462ece3ba21ef Mon Sep 17 00:00:00 2001 From: triton Date: Thu, 30 Jan 2014 15:00:36 +0000 Subject: [PATCH] Reworked parsing of preprocessed entities. Fixes macro expansions and translation units processing. --- src/CppParser/Parser.cpp | 175 ++++++++++++++++++-------------------- src/CppParser/Parser.h | 1 + src/Parser/Parser.cpp | 178 ++++++++++++++++++--------------------- src/Parser/Parser.h | 2 +- 4 files changed, 163 insertions(+), 193 deletions(-) diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index c201ef76..56bf0333 100644 --- a/src/CppParser/Parser.cpp +++ b/src/CppParser/Parser.cpp @@ -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(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) 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(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( return Entity; } + auto& P = C->getPreprocessor(); + PreprocessedEntity* Entity; switch(PPEntity->getKind()) @@ -2073,19 +1996,68 @@ PreprocessedEntity* Parser::WalkPreprocessedEntity( case clang::PreprocessedEntity::MacroDefinitionKind: { auto MD = cast(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) 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(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) const clang::DirectoryLookup *Dir; llvm::SmallVector 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) 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 M(new llvm::Module("", Ctx)); diff --git a/src/CppParser/Parser.h b/src/CppParser/Parser.h index ead70f95..ddb4f23a 100644 --- a/src/CppParser/Parser.h +++ b/src/CppParser/Parser.h @@ -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); diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index fbc53f0b..55f03a90 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -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(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) 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(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(II->getName())->Trim(); - macro->Expression = marshalString(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( return Entity; } + auto& P = C->getPreprocessor(); + CppSharp::AST::PreprocessedEntity^ Entity; switch(PPEntity->getKind()) { case PreprocessedEntity::MacroExpansionKind: { - const MacroExpansion* MD = cast(PPEntity); + auto MD = cast(PPEntity); Entity = gcnew CppSharp::AST::MacroExpansion(); std::string Text; @@ -2097,20 +2019,69 @@ CppSharp::AST::PreprocessedEntity^ Parser::WalkPreprocessedEntity( } case PreprocessedEntity::MacroDefinitionKind: { - const MacroDefinition* MD = cast(PPEntity); - Entity = gcnew CppSharp::AST::MacroDefinition(); - break; + auto MD = cast(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(II->getName())->Trim(); + Definition->Expression = clix::marshalString(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) 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(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) const clang::DirectoryLookup *Dir; llvm::SmallVector 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) AST = &C->getASTContext(); + auto FileName = clix::marshalString(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 M(new llvm::Module("", Ctx)); diff --git a/src/Parser/Parser.h b/src/Parser/Parser.h index b0ee04cd..4846bf3a 100644 --- a/src/Parser/Parser.h +++ b/src/Parser/Parser.h @@ -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: 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);