diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 88cca910..f6e8a599 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -606,28 +606,72 @@ CppSharp::Field^ Parser::WalkFieldCXX(clang::FieldDecl* FD, CppSharp::Class^ Cla //-----------------------------------// -CppSharp::Namespace^ Parser::GetNamespace(const clang::NamedDecl* ND) +CppSharp::TranslationUnit^ Parser::GetTranslationUnit(clang::SourceLocation Loc, + SourceLocationKind *Kind) { using namespace clang; - using namespace clix; - SourceLocation Loc = ND->getLocation(); + SourceManager& SM = C->getSourceManager(); + + if (Loc.isMacroID()) + Loc = SM.getExpansionLoc(Loc); + + StringRef File; + + auto LocKind = GetLocationKind(Loc); + switch(LocKind) + { + case SourceLocationKind::Invalid: + File = ""; + break; + case SourceLocationKind::Builtin: + File = ""; + break; + case SourceLocationKind::CommandLine: + File = ""; + break; + default: + File = SM.getFilename(Loc); + assert(!File.empty() && "Expected to find a valid file"); + break; + } + + if (Kind) + *Kind = LocKind; + + auto Unit = Lib->FindOrCreateModule(clix::marshalString(File)); + if (LocKind != SourceLocationKind::Invalid) + Unit->IsSystemHeader = SM.isInSystemHeader(Loc); + + return Unit; +} + +//-----------------------------------// + +CppSharp::TranslationUnit^ Parser::GetTranslationUnit(const clang::Decl* D) +{ + clang::SourceLocation Loc = D->getLocation(); SourceLocationKind Kind; - CppSharp::TranslationUnit^ M = GetModule(Loc, &Kind); + CppSharp::TranslationUnit^ Unit = GetTranslationUnit(Loc, &Kind); - if (Kind == SourceLocationKind::Builtin || - Kind == SourceLocationKind::CommandLine) - return M; + return Unit; +} + +CppSharp::DeclarationContext^ Parser::GetNamespace(clang::Decl* D, + clang::DeclContext *Ctx) +{ + using namespace clang; // If the declaration is at global scope, just early exit. - const DeclContext *Ctx = ND->getDeclContext(); if (Ctx->isTranslationUnit()) - return M; + return GetTranslationUnit(D); + + CppSharp::TranslationUnit^ Unit = GetTranslationUnit(cast(Ctx)); // Else we need to do a more expensive check to get all the namespaces, // and then perform a reverse iteration to get the namespaces in order. - typedef SmallVector ContextsTy; + typedef SmallVector ContextsTy; ContextsTy Contexts; for(; Ctx != nullptr; Ctx = Ctx->getParent()) @@ -636,12 +680,12 @@ CppSharp::Namespace^ Parser::GetNamespace(const clang::NamedDecl* ND) assert(Contexts.back()->isTranslationUnit()); Contexts.pop_back(); - CppSharp::Namespace^ NS = M; + CppSharp::DeclarationContext^ DC = Unit; for (auto I = Contexts.rbegin(), E = Contexts.rend(); I != E; ++I) { - const DeclContext* Ctx = *I; - + DeclContext* Ctx = *I; + switch(Ctx->getDeclKind()) { case Decl::Namespace: @@ -649,9 +693,9 @@ CppSharp::Namespace^ Parser::GetNamespace(const clang::NamedDecl* ND) const NamespaceDecl* ND = cast(Ctx); if (ND->isAnonymousNamespace()) continue; - auto Name = marshalString(ND->getName()); - NS = NS->FindCreateNamespace(Name, NS); - break; + auto Name = clix::marshalString(ND->getName()); + DC = DC->FindCreateNamespace(Name); + continue; } case Decl::LinkageSpec: { @@ -660,8 +704,8 @@ CppSharp::Namespace^ Parser::GetNamespace(const clang::NamedDecl* ND) } case Decl::CXXRecord: { - // FIXME: Ignore record namespaces... - // We might be able to translate these to C# nested types. + auto RD = cast(Ctx); + DC = WalkRecordCXX(RD); continue; } case Decl::ClassTemplateSpecialization: @@ -678,7 +722,12 @@ CppSharp::Namespace^ Parser::GetNamespace(const clang::NamedDecl* ND) } } } - return NS; + return DC; +} + +CppSharp::DeclarationContext^ Parser::GetNamespace(clang::Decl *D) +{ + return GetNamespace(D, D->getDeclContext()); } static CppSharp::PrimitiveType WalkBuiltinType(const clang::BuiltinType* Builtin) @@ -1327,50 +1376,6 @@ void Parser::WalkAST() //-----------------------------------// -CppSharp::TranslationUnit^ Parser::GetModule(clang::SourceLocation Loc, - SourceLocationKind *Kind) -{ - using namespace clang; - using namespace clix; - - SourceManager& SM = C->getSourceManager(); - - if (Loc.isMacroID()) - Loc = SM.getExpansionLoc(Loc); - - StringRef File; - - auto LocKind = GetLocationKind(Loc); - switch(LocKind) - { - case SourceLocationKind::Invalid: - File = ""; - break; - case SourceLocationKind::Builtin: - File = ""; - break; - case SourceLocationKind::CommandLine: - File = ""; - break; - default: - File = SM.getFilename(Loc); - assert(!File.empty() && "Expected to find a valid file"); - break; - } - - if (Kind) - *Kind = LocKind; - - auto Unit = Lib->FindOrCreateModule(marshalString(File)); - if (LocKind != SourceLocationKind::Invalid) - Unit->IsSystemHeader = SM.isInSystemHeader(Loc); - - return Unit; - -} - -//-----------------------------------// - void Parser::WalkMacros(clang::PreprocessingRecord* PR) { using namespace clang; @@ -1424,7 +1429,7 @@ void Parser::WalkMacros(clang::PreprocessingRecord* PR) macro->Name = marshalString(II->getName())->Trim(); macro->Expression = marshalString(Expression)->Trim(); - auto M = GetModule(BeginExpr); + auto M = GetTranslationUnit(BeginExpr); if( M != nullptr ) M->Macros->Add(macro); diff --git a/src/Parser/Parser.h b/src/Parser/Parser.h index db06fee0..d0c547ce 100644 --- a/src/Parser/Parser.h +++ b/src/Parser/Parser.h @@ -159,10 +159,12 @@ protected: void HandlePreprocessedEntities(clang::Decl* D, CppSharp::Declaration^); bool GetPreprocessedEntityText(clang::PreprocessedEntity*, std::string& Text); - - CppSharp::TranslationUnit^ GetModule(clang::SourceLocation Loc, + CppSharp::TranslationUnit^ GetTranslationUnit(clang::SourceLocation Loc, SourceLocationKind *Kind = 0); - CppSharp::Namespace^ GetNamespace(const clang::NamedDecl*); + CppSharp::TranslationUnit^ GetTranslationUnit(const clang::Decl*); + + CppSharp::DeclarationContext^ GetNamespace(clang::Decl*, clang::DeclContext*); + CppSharp::DeclarationContext^ GetNamespace(clang::Decl*); clang::CallingConv GetAbiCallConv(clang::CallingConv CC, bool IsInstMethod, bool IsVariadic);