diff --git a/include/clang-c/CXCppInterOp.h b/include/clang-c/CXCppInterOp.h index 361b64530..bc432943a 100644 --- a/include/clang-c/CXCppInterOp.h +++ b/include/clang-c/CXCppInterOp.h @@ -203,6 +203,21 @@ CXString clang_interpreter_searchLibrariesForSymbol(CXInterpreter I, const char* mangled_name, bool search_system); +typedef void* CXFuncAddr; + +/** + * Get the function address from the given mangled name. + * + * \param I The interpreter. + * + * \param mangled_name The mangled name of the function. + * + * \returns the address of the function given its potentially mangled name. + */ +CXFuncAddr +clang_interpreter_getFunctionAddressFromMangledName(CXInterpreter I, + const char* mangled_name); + /** * @} */ @@ -212,6 +227,8 @@ CXString clang_interpreter_searchLibrariesForSymbol(CXInterpreter I, */ typedef void* CXObject; +typedef void* CXFunction; + /** * \defgroup CPPINTEROP_TYPE_MANIP Type manipulations * @@ -223,6 +240,7 @@ typedef void* CXObject; */ enum CXQualTypeKind { CXQualType_Unexposed = 0, + CXQualType_Invalid = 1, // reserved for future use }; @@ -256,6 +274,11 @@ CXQualType clang_qualtype_getIntegerTypeFromEnumType(CXQualType type); */ size_t clang_qualtype_getSizeOfType(CXQualType type); +/** + * Checks if a C++ type derives from another. + */ +bool clang_qualtype_isTypeDerivedFrom(CXQualType derived, CXQualType base); + /** * @} */ @@ -270,12 +293,14 @@ size_t clang_qualtype_getSizeOfType(CXQualType type); * Describes the kind of entity that a scope refers to. */ enum CXScopeKind { - /** Generic declarations. */ CXScope_Unexposed = 0, - /** Function, methods, etc. */ - CXScope_Function = 1, + CXScope_Invalid = 1, + /** Function, methods, constructor etc. */ + CXScope_Function = 2, /** Variables. */ - CXScope_Variable = 2, + CXScope_Variable = 3, + /** Fields. */ + CXScope_Field = 4, // reserved for future use }; @@ -288,6 +313,9 @@ typedef struct { const void* meta; } CXScope; +// for debugging purposes +void clang_scope_dump(CXScope S); + /** * This will convert a class into its type, so for example, you can use it to * declare variables in it. @@ -423,6 +451,13 @@ CXString clang_scope_getQualifiedCompleteName(CXScope S); */ size_t clang_scope_getNumBases(CXScope S); +/** + * Gets a specific Base Class using its index. Typically GetNumBases() + * is used to get the number of Base Classes, and then that number can be used + * to iterate through the index value to get each specific base class. + */ +CXScope clang_scope_getBaseClass(CXScope S, size_t ibase); + /** * Checks if the supplied Derived Class is a sub-class of the provided Base * Class. @@ -440,8 +475,6 @@ int64_t clang_scope_getBaseClassOffset(CXScope derived, CXScope base); */ bool clang_scope_hasDefaultConstructor(CXScope S); -typedef void* CXFunction; - /** * Returns the default constructor of a class, if any. */ @@ -462,12 +495,110 @@ CXScope clang_scope_getDestructor(CXScope S); /** * Gets the return type of the provided function. */ -CXQualType clang_scope_getFunctionReturnType(CXScope S); +CXQualType clang_scope_getFunctionReturnType(CXScope func); /** * Gets the number of Arguments for the provided function. */ -size_t clang_scope_getFunctionNumArgs(CXScope S); +size_t clang_scope_getFunctionNumArgs(CXScope func); + +/** + * Gets the number of Required Arguments for the provided function. + */ +size_t clang_scope_getFunctionRequiredArgs(CXScope func); + +/** + * For each Argument of a function, you can get the Argument Type by providing + * the Argument Index, based on the number of arguments from the + * GetFunctionNumArgs() function. + */ +CXQualType clang_scope_getFunctionArgType(CXScope func, size_t iarg); + +/** + * Returns a stringified version of a given function signature in the form: + * void N::f(int i, double d, long l = 0, char ch = 'a'). + */ +CXString clang_scope_getFunctionSignature(CXScope func); + +/** + * Checks if a function was marked as \c =delete. + */ +bool clang_scope_isFunctionDeleted(CXScope func); + +/** + * Checks if a function is a templated function. + */ +bool clang_scope_isTemplatedFunction(CXScope func); + +/** + * This function performs a lookup to check if there is a templated function of + * that type. + */ +bool clang_scope_existsFunctionTemplate(const CXInterpreter I, const char* name, + CXScope parent); + +/** + * Checks if the provided parameter is a method. + */ +bool clang_scope_isMethod(CXScope method); + +/** + * Checks if the provided parameter is a 'Public' method. + */ +bool clang_scope_isPublicMethod(CXScope method); + +/** + * Checks if the provided parameter is a 'Protected' method. + */ +bool clang_scope_isProtectedMethod(CXScope method); + +/** + * Checks if the provided parameter is a 'Private' method. + */ +bool clang_scope_isPrivateMethod(CXScope method); + +/** + * Checks if the provided parameter is a 'Private' method. + */ +bool clang_scope_isPrivateMethod(CXScope method); + +/** + * Checks if the provided parameter is a Constructor. + */ +bool clang_scope_isConstructor(CXScope method); + +/** + * Checks if the provided parameter is a Destructor. + */ +bool clang_scope_isDestructor(CXScope method); + +/** + * Checks if the provided parameter is a 'Static' method. + */ +bool clang_scope_isStaticMethod(CXScope method); + +/** + * Returns the address of the function given its function declaration. + */ +CXFuncAddr clang_scope_getFunctionAddress(CXScope method); + +/** + * Checks if the provided parameter is a 'Virtual' method. + */ +bool clang_scope_isVirtualMethod(CXScope method); + +/** + * Gets all the Fields/Data Members of a Class. For now, it only gets non-static + * data members but in a future update, it may support getting static data + * members as well. + */ +// std::vector clang_scope_getDatamembers(CXScope method); + +/** + * This is a Lookup function to be used specifically for data members. + */ +CXScope clang_scope_lookupDatamember(const CXInterpreter I, const char* name, + CXScope parent); /** * @} @@ -534,21 +665,6 @@ void clang_interpreter_construct(CXInterpreter I, CXScope type, void* arena); void clang_interpreter_destruct(CXInterpreter I, CXObject This, CXScope type, bool withFree); -typedef void* CXFuncAddr; - -/** - * Get the function address from the given mangled name. - * - * \param I The interpreter. - * - * \param mangled_name The mangled name of the function. - * - * \returns the address of the function given its potentially mangled name. - */ -CXFuncAddr -clang_interpreter_getFunctionAddressFromMangledName(CXInterpreter I, - const char* mangled_name); - /** * An opaque pointer representing CppInterOp's JitCall, a class modeling * function calls for functions produced by the interpreter in compiled code. diff --git a/include/clang/Interpreter/CppInterOp.h b/include/clang/Interpreter/CppInterOp.h index 668790aac..53d93ce28 100644 --- a/include/clang/Interpreter/CppInterOp.h +++ b/include/clang/Interpreter/CppInterOp.h @@ -278,7 +278,7 @@ namespace Cpp { /// is used to get the number of Base Classes, and then that number /// can be used to iterate through the index value to get each specific /// base class. - CPPINTEROP_API TCppScope_t GetBaseClass(TCppType_t klass, TCppIndex_t ibase); + CPPINTEROP_API TCppScope_t GetBaseClass(TCppScope_t klass, TCppIndex_t ibase); /// Checks if the supplied Derived Class is a sub-class of the /// provided Base Class. diff --git a/lib/Interpreter/CXCppInterOp.cpp b/lib/Interpreter/CXCppInterOp.cpp index ad76f0dc5..0d0ddcfec 100644 --- a/lib/Interpreter/CXCppInterOp.cpp +++ b/lib/Interpreter/CXCppInterOp.cpp @@ -1,5 +1,6 @@ #include "clang-c/CXCppInterOp.h" #include "Compatibility.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/RecordLayout.h" @@ -147,6 +148,19 @@ CXString clang_interpreter_searchLibrariesForSymbol(CXInterpreter I, mangled_name, search_system)); } +CXFuncAddr +clang_interpreter_getFunctionAddressFromMangledName(CXInterpreter I, + const char* mangled_name) { + auto* interp = getInterpreter(I); + auto FDAorErr = compat::getSymbolAddress(*interp, mangled_name); + if (llvm::Error Err = FDAorErr.takeError()) + llvm::consumeError(std::move(Err)); // nullptr if missing + else + return llvm::jitTargetAddressToPointer(*FDAorErr); + + return nullptr; +} + static inline CXQualType makeCXQualType(const CXInterpreterImpl* I, clang::QualType Ty, CXQualTypeKind K = CXQualType_Unexposed) { @@ -197,7 +211,20 @@ size_t clang_qualtype_getSizeOfType(CXQualType type) { return TypeSize / 8; } -static inline bool isNullDecl(CXScope S) { return !S.data; } +bool clang_qualtype_isTypeDerivedFrom(CXQualType derived, CXQualType base) { + auto* I = getInterpreter(derived); + auto& SM = I->getSema().getSourceManager(); + auto fakeLoc = SM.getLocForStartOfFile(SM.getMainFileID()); + auto derivedType = getType(derived); + auto baseType = getType(base); + +#ifdef USE_CLING + cling::Interpreter::PushTransactionRAII RAII(I); +#endif + return I->getSema().IsDerivedFrom(fakeLoc, derivedType, baseType); +} + +static inline bool isNull(CXScope S) { return !S.data; } static inline clang::Decl* getDecl(CXScope S) { return static_cast(S.data); @@ -211,9 +238,11 @@ static inline compat::Interpreter* getInterpreter(CXScope S) { return getInterpreter(reinterpret_cast(S.meta)); } +void clang_scope_dump(CXScope S) { getDecl(S)->dump(); } + CXQualType clang_scope_getTypeFromScope(CXScope S) { - if (isNullDecl(S)) - return makeCXQualType(getMeta(S), clang::QualType()); + if (isNull(S)) + return makeCXQualType(getMeta(S), clang::QualType(), CXQualType_Invalid); auto* D = getDecl(S); if (const auto* VD = llvm::dyn_cast(D)) @@ -235,7 +264,7 @@ bool clang_scope_isClass(CXScope S) { } bool clang_scope_isComplete(CXScope S) { - if (isNullDecl(S)) + if (isNull(S)) return false; auto* D = getDecl(S); @@ -270,8 +299,465 @@ size_t clang_scope_sizeOf(CXScope S) { return 0; } +bool clang_scope_isTemplate(CXScope S) { + return llvm::isa_and_nonnull(getDecl(S)); +} + +bool clang_scope_isTemplateSpecialization(CXScope S) { + return llvm::isa_and_nonnull( + getDecl(S)); +} + +bool clang_scope_isTypedefed(CXScope S) { + return llvm::isa_and_nonnull(getDecl(S)); +} + +bool clang_scope_isAbstract(CXScope S) { + if (auto* CXXRD = llvm::dyn_cast_or_null(getDecl(S))) + return CXXRD->isAbstract(); + return false; +} + +bool clang_scope_isEnumScope(CXScope S) { + return llvm::isa_and_nonnull(getDecl(S)); +} + +bool clang_scope_isEnumConstant(CXScope S) { + return llvm::isa_and_nonnull(getDecl(S)); +} + +bool clang_scope_isEnumType(CXScope S) { + auto T = clang_scope_getTypeFromScope(S); + return getType(T)->isEnumeralType(); +} + +CXQualType clang_scope_getIntegerTypeFromEnumScope(CXScope S) { + auto* ED = llvm::dyn_cast_or_null(getDecl(S)); + if (ED) + return makeCXQualType(getMeta(S), ED->getIntegerType()); + + return makeCXQualType(getMeta(S), clang::QualType(), CXQualType_Invalid); +} + +CXQualType clang_scope_getEnumConstantType(CXScope S) { + if (isNull(S)) + return makeCXQualType(getMeta(S), clang::QualType(), CXQualType_Invalid); + + auto* ECD = llvm::dyn_cast_or_null(getDecl(S)); + if (ECD) + return makeCXQualType(getMeta(S), ECD->getType()); + + return makeCXQualType(getMeta(S), clang::QualType(), CXQualType_Invalid); +} + +size_t clang_scope_getEnumConstantValue(CXScope S) { + auto* ECD = llvm::dyn_cast_or_null(getDecl(S)); + if (ECD) { + const llvm::APSInt& Val = ECD->getInitVal(); + return Val.getExtValue(); + } + return 0; +} + +bool clang_scope_isVariable(CXScope S) { + return llvm::isa_and_nonnull(getDecl(S)); +} + +CXString clang_scope_getName(CXScope S) { + auto* D = getDecl(S); + + if (llvm::isa_and_nonnull(D)) + return createCXString(""); + + if (auto* ND = llvm::dyn_cast_or_null(D)) + return createCXString(ND->getNameAsString()); + + return createCXString(""); +} + +CXString clang_scope_getCompleteName(CXScope S) { + auto& C = getInterpreter(S)->getSema().getASTContext(); + auto* D = getDecl(S); + + if (auto* ND = llvm::dyn_cast_or_null(D)) { + if (auto* TD = llvm::dyn_cast(ND)) { + std::string type_name; + clang::QualType QT = C.getTagDeclType(TD); + clang::PrintingPolicy Policy = C.getPrintingPolicy(); + Policy.SuppressUnwrittenScope = true; + Policy.SuppressScope = true; + Policy.AnonymousTagLocations = false; + QT.getAsStringInternal(type_name, Policy); + + return createCXString(type_name); + } + + return createCXString(ND->getNameAsString()); + } + + if (llvm::isa_and_nonnull(D)) + return createCXString(""); + + return createCXString(""); +} + +CXString clang_scope_getQualifiedName(CXScope S) { + auto* D = getDecl(S); + if (auto* ND = llvm::dyn_cast_or_null(D)) + return createCXString(ND->getQualifiedNameAsString()); + + if (llvm::isa_and_nonnull(D)) + return createCXString(""); + + return createCXString(""); +} + +CXString clang_scope_getQualifiedCompleteName(CXScope S) { + auto& C = getInterpreter(S)->getSema().getASTContext(); + auto* D = getDecl(S); + + if (auto* ND = llvm::dyn_cast_or_null(D)) { + if (auto* TD = llvm::dyn_cast(ND)) { + std::string type_name; + clang::QualType QT = C.getTagDeclType(TD); + QT.getAsStringInternal(type_name, C.getPrintingPolicy()); + + return createCXString(type_name); + } + + return createCXString(ND->getQualifiedNameAsString()); + } + + if (llvm::isa_and_nonnull(D)) { + return createCXString(""); + } + + return createCXString(""); +} + +size_t clang_scope_getNumBases(CXScope S) { + auto* D = getDecl(S); + + if (auto* CXXRD = llvm::dyn_cast_or_null(D)) { + if (CXXRD->hasDefinition()) + return CXXRD->getNumBases(); + } + + return 0; +} + +CXScope clang_scope_getBaseClass(CXScope S, size_t ibase) { + auto* D = getDecl(S); + auto* CXXRD = llvm::dyn_cast_or_null(D); + if (!CXXRD || CXXRD->getNumBases() <= ibase) + return makeCXScope(getMeta(S), nullptr, CXScope_Invalid); + + auto type = (CXXRD->bases_begin() + ibase)->getType(); + if (auto RT = type->getAs()) + return makeCXScope(getMeta(S), RT->getDecl()); + + return makeCXScope(getMeta(S), nullptr, CXScope_Invalid); +} + +bool clang_scope_isSubclass(CXScope derived, CXScope base) { + if (isNull(derived) || isNull(base)) + return false; + + auto* D = getDecl(derived); + auto* B = getDecl(base); + + if (D == B) + return true; + + if (!llvm::isa(D) || + !llvm::isa(B)) + return false; + + return clang_qualtype_isTypeDerivedFrom(clang_scope_getTypeFromScope(derived), + clang_scope_getTypeFromScope(base)); +} + +namespace Cpp { +unsigned ComputeBaseOffset(const clang::ASTContext& Context, + const clang::CXXRecordDecl* DerivedRD, + const clang::CXXBasePath& Path); +} + +int64_t clang_scope_getBaseClassOffset(CXScope derived, CXScope base) { + auto* D = getDecl(derived); + auto* B = getDecl(base); + + if (D == B) + return 0; + + assert(D || B); + + if (!llvm::isa(D) || + !llvm::isa(B)) + return -1; + + auto* DCXXRD = llvm::cast(D); + auto* BCXXRD = llvm::cast(B); + clang::CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + DCXXRD->isDerivedFrom(BCXXRD, Paths); + + auto* I = getInterpreter(derived); + return Cpp::ComputeBaseOffset(I->getSema().getASTContext(), DCXXRD, + Paths.front()); +} + +bool clang_scope_hasDefaultConstructor(CXScope S) { + auto* D = getDecl(S); + + if (auto* CXXRD = llvm::dyn_cast_or_null(D)) + return CXXRD->hasDefaultConstructor(); + + return false; +} + +CXScope clang_scope_getDefaultConstructor(CXScope S) { + if (!clang_scope_hasDefaultConstructor(S)) + return makeCXScope(getMeta(S), nullptr, CXScope_Invalid); + + auto* CXXRD = llvm::dyn_cast_or_null(getDecl(S)); + if (!CXXRD) + return makeCXScope(getMeta(S), nullptr, CXScope_Invalid); + + auto* Res = getInterpreter(S)->getSema().LookupDefaultConstructor(CXXRD); + return makeCXScope(getMeta(S), Res, CXScope_Function); +} + +CXScope clang_scope_getDestructor(CXScope S) { + auto* D = getDecl(S); + + if (auto* CXXRD = llvm::dyn_cast_or_null(D)) { + getInterpreter(S)->getSema().ForceDeclarationOfImplicitMembers(CXXRD); + return makeCXScope(getMeta(S), CXXRD->getDestructor(), CXScope_Function); + } + + return makeCXScope(getMeta(S), nullptr, CXScope_Invalid); +} + +CXQualType clang_scope_getFunctionReturnType(CXScope func) { + auto* D = getDecl(func); + if (auto* FD = llvm::dyn_cast_or_null(D)) + return makeCXQualType(getMeta(func), FD->getReturnType()); + + if (auto* FD = llvm::dyn_cast_or_null(D)) { + auto* FTD = FD->getTemplatedDecl(); + return makeCXQualType(getMeta(func), FTD->getReturnType()); + } + + return makeCXQualType(getMeta(func), clang::QualType(), CXQualType_Invalid); +} + +size_t clang_scope_getFunctionNumArgs(CXScope func) { + auto* D = getDecl(func); + if (auto* FD = llvm::dyn_cast_or_null(D)) + return FD->getNumParams(); + + if (auto* FD = llvm::dyn_cast_or_null(D)) + return FD->getTemplatedDecl()->getNumParams(); + + return 0; +} + +size_t clang_scope_getFunctionRequiredArgs(CXScope func) { + auto* D = getDecl(func); + if (auto* FD = llvm::dyn_cast_or_null(D)) + return FD->getMinRequiredArguments(); + + if (auto* FD = llvm::dyn_cast_or_null(D)) + return FD->getTemplatedDecl()->getMinRequiredArguments(); + + return 0; +} + +CXQualType clang_scope_getFunctionArgType(CXScope func, size_t iarg) { + auto* D = getDecl(func); + + if (auto* FD = llvm::dyn_cast_or_null(D)) { + if (iarg < FD->getNumParams()) { + auto* PVD = FD->getParamDecl(iarg); + return makeCXQualType(getMeta(func), PVD->getOriginalType()); + } + } + + return makeCXQualType(getMeta(func), clang::QualType(), CXQualType_Invalid); +} + +CXString clang_scope_getFunctionSignature(CXScope func) { + if (isNull(func)) + return createCXString(""); + + auto* D = getDecl(func); + if (auto* FD = llvm::dyn_cast(D)) { + std::string Signature; + llvm::raw_string_ostream SS(Signature); + auto& C = getInterpreter(func)->getSema().getASTContext(); + clang::PrintingPolicy Policy = C.getPrintingPolicy(); + // Skip printing the body + Policy.TerseOutput = true; + Policy.FullyQualifiedName = true; + Policy.SuppressDefaultTemplateArgs = false; + FD->print(SS, Policy); + SS.flush(); + return createCXString(Signature); + } + + return createCXString(""); +} + +bool clang_scope_isFunctionDeleted(CXScope func) { + auto* FD = llvm::cast(getDecl(func)); + return FD->isDeleted(); +} + +bool clang_scope_isTemplatedFunction(CXScope func) { + auto* D = getDecl(func); + if (llvm::isa_and_nonnull(D)) + return true; + + if (auto* FD = llvm::dyn_cast_or_null(D)) { + auto TK = FD->getTemplatedKind(); + return TK == clang::FunctionDecl::TemplatedKind:: + TK_FunctionTemplateSpecialization || + TK == clang::FunctionDecl::TemplatedKind:: + TK_DependentFunctionTemplateSpecialization || + TK == clang::FunctionDecl::TemplatedKind::TK_FunctionTemplate; + } + + return false; +} + +bool clang_scope_existsFunctionTemplate(const CXInterpreter I, const char* name, + CXScope parent) { + clang::DeclContext* Within = nullptr; + if (!isNull(parent)) { + auto* D = getDecl(parent); + Within = llvm::dyn_cast(D); + } + + auto& S = getInterpreter(I)->getSema(); + auto* ND = Cpp::Cpp_utils::Lookup::Named(&S, name, Within); + + if ((intptr_t)ND == (intptr_t)0) + return false; + + if ((intptr_t)ND != (intptr_t)-1) + return clang_scope_isTemplatedFunction(makeCXScope(I, ND)); + + // FIXME: Cycle through the Decls and check if there is a templated function + return true; +} + +bool clang_scope_isMethod(CXScope method) { + auto* D = getDecl(method); + return llvm::dyn_cast_or_null(D); +} + +bool clang_scope_isPublicMethod(CXScope method) { + auto* D = getDecl(method); + if (auto* CXXMD = llvm::dyn_cast_or_null(D)) + return CXXMD->getAccess() == clang::AccessSpecifier::AS_public; + + return false; +} + +bool clang_scope_isProtectedMethod(CXScope method) { + auto* D = getDecl(method); + if (auto* CXXMD = llvm::dyn_cast_or_null(D)) + return CXXMD->getAccess() == clang::AccessSpecifier::AS_protected; + + return false; +} + +bool clang_scope_isPrivateMethod(CXScope method) { + auto* D = getDecl(method); + if (auto* CXXMD = llvm::dyn_cast_or_null(D)) + return CXXMD->getAccess() == clang::AccessSpecifier::AS_private; + + return false; +} + +bool clang_scope_isConstructor(CXScope method) { + auto* D = getDecl(method); + return llvm::isa_and_nonnull(D); +} + +bool clang_scope_isDestructor(CXScope method) { + auto* D = getDecl(method); + return llvm::isa_and_nonnull(D); +} + +bool clang_scope_isStaticMethod(CXScope method) { + auto* D = getDecl(method); + if (auto* CXXMD = llvm::dyn_cast_or_null(D)) + return CXXMD->isStatic(); + + return false; +} + +CXFuncAddr clang_scope_getFunctionAddress(CXScope method) { + auto* D = getDecl(method); + auto* I = getInterpreter(method); + + const auto get_mangled_name = [I](clang::FunctionDecl* FD) { + auto MangleCtx = I->getSema().getASTContext().createMangleContext(); + + if (!MangleCtx->shouldMangleDeclName(FD)) { + return FD->getNameInfo().getName().getAsString(); + } + + std::string mangled_name; + llvm::raw_string_ostream ostream(mangled_name); + + MangleCtx->mangleName(FD, ostream); + + ostream.flush(); + delete MangleCtx; + + return mangled_name; + }; + + if (auto* FD = llvm::dyn_cast_or_null(D)) { + auto FDAorErr = compat::getSymbolAddress(*I, get_mangled_name(FD).c_str()); + if (llvm::Error Err = FDAorErr.takeError()) + llvm::consumeError(std::move(Err)); // nullptr if missing + else + return llvm::jitTargetAddressToPointer(*FDAorErr); + } + + return nullptr; +} + +bool clang_scope_isVirtualMethod(CXScope method) { + auto* D = getDecl(method); + if (auto* CXXMD = llvm::dyn_cast_or_null(D)) + return CXXMD->isVirtual(); + + return false; +} + +CXScope clang_scope_lookupDatamember(const CXInterpreter I, const char* name, + CXScope parent) { + clang::DeclContext* Within = 0; + if (!isNull(parent)) + Within = llvm::dyn_cast(getDecl(parent)); + + auto& S = getInterpreter(I)->getSema(); + auto* ND = Cpp::Cpp_utils::Lookup::Named(&S, name, Within); + if (ND && ND != (clang::NamedDecl*)-1) { + if (llvm::isa_and_nonnull(ND)) { + return makeCXScope(I, ND, CXScope_Field); + } + } + + return makeCXScope(I, nullptr, CXScope_Invalid); +} + // namespace Cpp { -// std::string GetCompleteNameImpl(clang::ASTContext& C, clang::Decl* D); // clang::Decl* GetNamedImpl(clang::Sema* sema, const std::string& name, // clang::Decl* parent); @@ -322,7 +808,8 @@ size_t clang_scope_sizeOf(CXScope S) { // if (!ND || ND == (clang::NamedDecl*)-1) // return nullptr; -// if (llvm::isa(ND) || llvm::isa(ND) +// if (llvm::isa(ND) || +// llvm::isa(ND) // || // llvm::isa(ND) || // llvm::isa(ND)) @@ -350,27 +837,14 @@ size_t clang_scope_sizeOf(CXScope S) { // NOLINT(*-cast) return interp->getSema().LookupDefaultConstructor(CXXRD); // } -// void clang_interpreter_destruct(CXInterpreter I, CXObject This, CXScope type, +// void clang_interpreter_destruct(CXInterpreter I, CXObject This, CXScope +// type, // bool withFree) { // auto* interp = static_cast(I); // auto* D = reinterpret_cast(type); // NOLINT(*-cast) // Cpp::DestructImpl(*interp, This, D, withFree); // } -// CXFuncAddr -// clang_interpreter_getFunctionAddressFromMangledName(CXInterpreter I, -// const char* mangled_name) -// { -// auto* interp = static_cast(I); -// auto FDAorErr = compat::getSymbolAddress(*interp, mangled_name); -// if (llvm::Error Err = FDAorErr.takeError()) -// llvm::consumeError(std::move(Err)); // nullptr if missing -// else -// return llvm::jitTargetAddressToPointer(*FDAorErr); - -// return nullptr; -// } - // void clang_jitcall_dispose(CXJitCall J) { // delete reinterpret_cast(J); // NOLINT(*-owning-memory, // *-cast) @@ -405,8 +879,9 @@ size_t clang_scope_sizeOf(CXScope S) { // } // bool clang_jitcall_insertOrReplaceJitSymbol(CXInterpreter I, -// const char* linker_mangled_name, -// uint64_t address) { +// const char* +// linker_mangled_name, uint64_t +// address) { // return Cpp::InsertOrReplaceJitSymbolImpl( // *static_cast(I), linker_mangled_name, address); // } \ No newline at end of file diff --git a/lib/Interpreter/CppInterOp.cpp b/lib/Interpreter/CppInterOp.cpp index 4e53a9961..9fdf0a052 100644 --- a/lib/Interpreter/CppInterOp.cpp +++ b/lib/Interpreter/CppInterOp.cpp @@ -410,7 +410,10 @@ namespace Cpp { return ""; } - std::string GetCompleteNameImpl(ASTContext& C, Decl* D) { + std::string GetCompleteName(TCppScope_t klass) { + auto& C = getSema().getASTContext(); + auto* D = (Decl*)klass; + if (auto *ND = llvm::dyn_cast_or_null(D)) { if (auto *TD = llvm::dyn_cast(ND)) { std::string type_name; @@ -434,12 +437,6 @@ namespace Cpp { return ""; } - std::string GetCompleteName(TCppScope_t klass) { - auto* D = static_cast(klass); - auto& C = getInterp().getSema().getASTContext(); - return GetCompleteNameImpl(C, D); - } - std::string GetQualifiedName(TCppScope_t klass) { auto *D = (Decl *) klass; if (auto *ND = llvm::dyn_cast_or_null(D)) { @@ -454,7 +451,10 @@ namespace Cpp { } //FIXME: Figure out how to merge with GetCompleteName. - std::string GetQualifiedCompleteNameImpl(ASTContext& C, Decl* D) { + std::string GetQualifiedCompleteName(TCppScope_t klass) { + auto& C = getSema().getASTContext(); + auto* D = (Decl*)klass; + if (auto *ND = llvm::dyn_cast_or_null(D)) { if (auto *TD = llvm::dyn_cast(ND)) { std::string type_name; @@ -474,12 +474,6 @@ namespace Cpp { return ""; } - std::string GetQualifiedCompleteName(TCppType_t klass) { - auto* D = static_cast(klass); - auto& C = getInterp().getSema().getASTContext(); - return GetQualifiedCompleteNameImpl(C, D); - } - std::vector GetUsingNamespaces(TCppScope_t scope) { auto *D = (clang::Decl *) scope; @@ -659,12 +653,12 @@ namespace Cpp { } // Copied from VTableBuilder.cpp - // This is an internal helper function for the CppInterOp library (as evident - // by the 'static' declaration), while the similar GetBaseClassOffset() + // This is an internal helper function for the CppInterOp library, + // while the similar GetBaseClassOffset() // function below is exposed to library users. - static unsigned ComputeBaseOffset(const ASTContext &Context, - const CXXRecordDecl *DerivedRD, - const CXXBasePath &Path) { + unsigned ComputeBaseOffset(const ASTContext& Context, + const CXXRecordDecl* DerivedRD, + const CXXBasePath& Path) { CharUnits NonVirtualOffset = CharUnits::Zero(); unsigned NonVirtualStart = 0; @@ -704,7 +698,6 @@ namespace Cpp { return (NonVirtualOffset + VirtualOffset).getQuantity(); } return NonVirtualOffset.getQuantity(); - } int64_t GetBaseClassOffset(TCppScope_t derived, TCppScope_t base) {