diff --git a/src/Bridge/Declaration.cs b/src/Bridge/Declaration.cs index a39bbd6b..ad71db57 100644 --- a/src/Bridge/Declaration.cs +++ b/src/Bridge/Declaration.cs @@ -153,10 +153,14 @@ namespace CppSharp // Passes that should not be run on this declaration. public ISet ExcludeFromPasses; + // List of preprocessed entities attached to this declaration. + public IList PreprocessedEntities; + protected Declaration() { IgnoreFlags = IgnoreFlags.None; ExcludeFromPasses = new HashSet(); + PreprocessedEntities = new List(); } protected Declaration(string name) @@ -187,24 +191,6 @@ namespace CppSharp } } - /// - /// Represents a C preprocessor macro definition. - /// - public class MacroDefinition : Declaration - { - // Contains the macro definition text. - public string Expression; - - public MacroDefinition() - { - } - - public override T Visit(IDeclVisitor visitor) - { - return visitor.VisitMacroDefinition(this); - } - } - public interface IDeclVisitor { T VisitDeclaration(Declaration decl); diff --git a/src/Bridge/Preprocessor.cs b/src/Bridge/Preprocessor.cs new file mode 100644 index 00000000..e1a57f7c --- /dev/null +++ b/src/Bridge/Preprocessor.cs @@ -0,0 +1,50 @@ +namespace CppSharp +{ + /// + /// Base class that describes a preprocessed entity, which may + /// be a preprocessor directive or macro expansion. + /// + public abstract class PreprocessedEntity : Declaration + { + + } + + /// + /// Represents a C preprocessor macro expansion. + /// + public class MacroExpansion : PreprocessedEntity + { + // Contains the macro expansion text. + public string Text; + + public MacroDefinition Definition; + + public MacroExpansion() + { + } + + public override T Visit(IDeclVisitor visitor) + { + //return visitor.VisitMacroExpansion(this); + return default(T); + } + } + + /// + /// Represents a C preprocessor macro definition. + /// + public class MacroDefinition : PreprocessedEntity + { + // Contains the macro definition text. + public string Expression; + + public MacroDefinition() + { + } + + public override T Visit(IDeclVisitor visitor) + { + return visitor.VisitMacroDefinition(this); + } + } +} diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 73f1611c..00b8e35f 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -1409,6 +1409,64 @@ void Parser::HandleComments(clang::Decl* D, CppSharp::Declaration^ Decl) //-----------------------------------// +bool Parser::GetPreprocessedEntityText(clang::PreprocessedEntity* PE, std::string& Text) +{ + using namespace clang; + SourceManager& SM = C->getSourceManager(); + const LangOptions &LangOpts = C->getLangOpts(); + + auto Range = CharSourceRange::getTokenRange(PE->getSourceRange()); + + bool Invalid; + Text = Lexer::getSourceText(Range, SM, LangOpts, &Invalid); + + return !Invalid && !Text.empty(); +} + +void Parser::HandlePreprocessedEntities(clang::Decl* D, CppSharp::Declaration^ Decl) +{ + using namespace clang; + auto PPRecord = C->getPreprocessor().getPreprocessingRecord(); + + auto SourceRange = D->getSourceRange(); + auto Range = PPRecord->getPreprocessedEntitiesInRange(SourceRange); + + for (auto it = Range.first; it != Range.second; ++it) + { + PreprocessedEntity* PPEntity = (*it); + + CppSharp::PreprocessedEntity^ Entity; + switch(PPEntity->getKind()) + { + case PreprocessedEntity::MacroExpansionKind: + { + const MacroExpansion* MD = cast(PPEntity); + Entity = gcnew CppSharp::MacroExpansion(); + + std::string Text; + if (!GetPreprocessedEntityText(PPEntity, Text)) + continue; + + static_cast(Entity)->Text = + clix::marshalString(Text); + break; + } + case PreprocessedEntity::MacroDefinitionKind: + { + const MacroDefinition* MD = cast(PPEntity); + Entity = gcnew CppSharp::MacroDefinition(); + break; + } + default: + break; + } + + Decl->PreprocessedEntities->Add(Entity); + } +} + +//-----------------------------------// + CppSharp::Declaration^ Parser::WalkDeclarationDef(clang::Decl* D) { return WalkDeclaration(D, 0, /*IgnoreSystemDecls=*/true, @@ -1622,6 +1680,14 @@ CppSharp::Declaration^ Parser::WalkDeclaration(clang::Decl* D, clang::TypeLoc* T break; } }; + if (Decl) + { + HandlePreprocessedEntities(D, Decl); + + if (const ValueDecl *VD = dyn_cast_or_null(D)) + Decl->IsDependent = VD->getType()->isDependentType(); + } + return Decl; } diff --git a/src/Parser/Parser.h b/src/Parser/Parser.h index 1b02df27..faf5a28c 100644 --- a/src/Parser/Parser.h +++ b/src/Parser/Parser.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include "CXXABI.h" @@ -131,6 +132,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^); + bool GetPreprocessedEntityText(clang::PreprocessedEntity*, std::string& Text); CppSharp::TranslationUnit^ GetModule(clang::SourceLocation Loc); CppSharp::Namespace^ GetNamespace(const clang::NamedDecl*);