- 
                Notifications
    
You must be signed in to change notification settings  - Fork 15.1k
 
Add __attribute__((visibility("default"))) attribute to certain symbols to stop them being hidden when linking clangInterpreter library to other libraries during Emscripten build #146786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| 
          
 @llvm/pr-subscribers-llvm-adt @llvm/pr-subscribers-clang Author: None (mcbarton) Changes@sbc100 Currently CppInterOp links its Emscripten shared library to the Emscripten static library libclangInterpreter.a . Certain symbols get hidden in libclangInterOp.a due to the -fvisibility-inlines-hidden flag when building an Emscripten build of llvm. This causes the CppInterOp to have to manually export these in a non Emscripten recommended way (see https://github.com/compiler-research/CppInterOp/blob/main/lib/CppInterOp/exports.ld ). This patch would allow us to avoid this method, by marking these symbols are visible, instead of hidden. This may not be the best approach to stop these symbols being hidden during an Emscripten build of llvm, to avoid CppInterOps currently hacky approach to making them available after linking to libclangInterpreter.a, but this is the best I could come up with. I am open to other suggestions. cc @vgvassilev Patch is 24.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146786.diff 19 Files Affected: 
 diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b13bdd5642977..3b05d83944052 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3895,7 +3895,7 @@ void ASTContext::adjustExceptionSpec(
 
 /// getComplexType - Return the uniqued reference to the type for a complex
 /// number with the specified element type.
-QualType ASTContext::getComplexType(QualType T) const {
+__attribute__((visibility("default"))) QualType ASTContext::getComplexType(QualType T) const {
   // Unique pointers, to guarantee there is only one pointer of a particular
   // structure.
   llvm::FoldingSetNodeID ID;
@@ -4079,7 +4079,7 @@ QualType ASTContext::getBlockPointerType(QualType T) const {
 
 /// getLValueReferenceType - Return the uniqued reference to the type for an
 /// lvalue reference to the specified type.
-QualType
+__attribute__((visibility("default"))) QualType
 ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const {
   assert((!T->isPlaceholderType() ||
           T->isSpecificPlaceholderType(BuiltinType::UnknownAny)) &&
@@ -5251,7 +5251,7 @@ QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl,
 
 /// getTypeDeclType - Return the unique reference to the type for the
 /// specified type declaration.
-QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const {
+__attribute__((visibility("default"))) QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const {
   assert(Decl && "Passed null for Decl param");
   assert(!Decl->TypeForDecl && "TypeForDecl present in slow case");
 
@@ -13125,7 +13125,7 @@ VTableContextBase *ASTContext::getVTableContext() {
   return VTContext.get();
 }
 
-MangleContext *ASTContext::createMangleContext(const TargetInfo *T) {
+__attribute__((visibility("default"))) MangleContext *ASTContext::createMangleContext(const TargetInfo *T) {
   if (!T)
     T = Target;
   switch (T->getCXXABI().getKind()) {
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 5cdf75d71e4d7..c6d9cfc918bee 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2255,7 +2255,7 @@ bool VarDecl::isInExternCXXContext() const {
 
 VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }
 
-VarDecl::DefinitionKind
+__attribute__((visibility("default"))) VarDecl::DefinitionKind
 VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
   if (isThisDeclarationADemotedDefinition())
     return DeclarationOnly;
@@ -3763,7 +3763,7 @@ unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
 /// getNumParams - Return the number of parameters this function must have
 /// based on its FunctionType.  This is the length of the ParamInfo array
 /// after it has been created.
-unsigned FunctionDecl::getNumParams() const {
+__attribute__((visibility("default"))) unsigned FunctionDecl::getNumParams() const {
   const auto *FPT = getType()->getAs<FunctionProtoType>();
   return FPT ? FPT->getNumParams() : 0;
 }
@@ -4200,7 +4200,7 @@ bool FunctionDecl::isTemplateInstantiation() const {
   return clang::isTemplateInstantiation(getTemplateSpecializationKind());
 }
 
-FunctionDecl *
+__attribute__((visibility("default"))) FunctionDecl *
 FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
   // If this is a generic lambda call operator specialization, its
   // instantiation pattern is always its primary template's pattern
@@ -4265,7 +4265,7 @@ FunctionDecl::getTemplateSpecializationInfo() const {
       TemplateOrSpecialization);
 }
 
-const TemplateArgumentList *
+__attribute__((visibility("default"))) const TemplateArgumentList *
 FunctionDecl::getTemplateSpecializationArgs() const {
   if (FunctionTemplateSpecializationInfo *Info =
           dyn_cast_if_present<FunctionTemplateSpecializationInfo *>(
@@ -5143,7 +5143,7 @@ RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C,
   return R;
 }
 
-bool RecordDecl::isInjectedClassName() const {
+__attribute__((visibility("default"))) bool RecordDecl::isInjectedClassName() const {
   return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
     cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
 }
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 13c46fdbff96a..83441e9bdd068 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -526,7 +526,7 @@ TranslationUnitDecl *Decl::getTranslationUnitDecl() {
   return cast<TranslationUnitDecl>(DC);
 }
 
-ASTContext &Decl::getASTContext() const {
+__attribute__((visibility("default"))) ASTContext &Decl::getASTContext() const {
   return getTranslationUnitDecl()->getASTContext();
 }
 
@@ -613,7 +613,7 @@ ExternalSourceSymbolAttr *Decl::getExternalSourceSymbolAttr() const {
   return nullptr;
 }
 
-bool Decl::hasDefiningAttr() const {
+__attribute__((visibility("default"))) bool Decl::hasDefiningAttr() const {
   return hasAttr<AliasAttr>() || hasAttr<IFuncAttr>() ||
          hasAttr<LoaderUninitializedAttr>();
 }
@@ -1047,7 +1047,7 @@ void Decl::addAttr(Attr *A) {
   Attrs.insert(I, A);
 }
 
-const AttrVec &Decl::getAttrs() const {
+__attribute__((visibility("default"))) const AttrVec &Decl::getAttrs() const {
   assert(HasAttrs && "No attrs to get!");
   return getASTContext().getDeclAttrs(this);
 }
@@ -1065,7 +1065,7 @@ Decl *Decl::castFromDeclContext (const DeclContext *D) {
   }
 }
 
-DeclContext *Decl::castToDeclContext(const Decl *D) {
+__attribute__((visibility("default"))) DeclContext *Decl::castToDeclContext(const Decl *D) {
   Decl::Kind DK = D->getKind();
   switch(DK) {
 #define DECL(NAME, BASE)
@@ -1291,7 +1291,7 @@ DeclContext::DeclContext(Decl::Kind K) {
   setUseQualifiedLookup(false);
 }
 
-bool DeclContext::classof(const Decl *D) {
+__attribute__((visibility("default"))) bool DeclContext::classof(const Decl *D) {
   Decl::Kind DK = D->getKind();
   switch (DK) {
 #define DECL(NAME, BASE)
@@ -1662,7 +1662,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
   return List.getLookupResult();
 }
 
-DeclContext::decl_iterator DeclContext::decls_begin() const {
+__attribute__((visibility("default"))) DeclContext::decl_iterator DeclContext::decls_begin() const {
   if (hasExternalLexicalStorage())
     LoadLexicalDeclsFromExternalStorage();
   return decl_iterator(FirstDecl);
@@ -1891,7 +1891,7 @@ void DeclContext::buildLookupImpl(DeclContext *DCtx, bool Internal) {
   }
 }
 
-DeclContext::lookup_result
+__attribute__((visibility("default"))) DeclContext::lookup_result
 DeclContext::lookup(DeclarationName Name) const {
   // For transparent DeclContext, we should lookup in their enclosing context.
   if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export)
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 5035f2d33b0a1..9a1a35a39df36 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -549,7 +549,7 @@ void ClassTemplateDecl::LoadLazySpecializations(
   loadLazySpecializationsImpl(OnlyPartial);
 }
 
-llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
+__attribute__((visibility("default"))) llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
 ClassTemplateDecl::getSpecializations() const {
   LoadLazySpecializations();
   return getCommonPtr()->Specializations;
@@ -1451,7 +1451,7 @@ void VarTemplateSpecializationDecl::getNameForDiagnostic(
   }
 }
 
-VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
+__attribute__((visibility("default"))) VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
   if (const auto *PartialSpec =
           SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
     return PartialSpec->PartialSpecialization->getSpecializedTemplate();
diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp
index 9652fdbc4e125..fad5f316f1040 100644
--- a/clang/lib/AST/Mangle.cpp
+++ b/clang/lib/AST/Mangle.cpp
@@ -118,7 +118,7 @@ static CCMangling getCallingConvMangling(const ASTContext &Context,
   }
 }
 
-bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
+__attribute__((visibility("default"))) bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
   const ASTContext &ASTContext = getASTContext();
 
   CCMangling CC = getCallingConvMangling(ASTContext, D);
@@ -152,7 +152,7 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
   return shouldMangleCXXName(D);
 }
 
-void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
+__attribute__((visibility("default"))) void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) {
   const ASTContext &ASTContext = getASTContext();
   const NamedDecl *D = cast<NamedDecl>(GD.getDecl());
 
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index e5a1ab2ff8906..128b46b3d46d9 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -650,7 +650,7 @@ template <> const CountAttributedType *Type::getAs() const {
 /// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic
 /// sugar off the given type.  This should produce an object of the
 /// same dynamic type as the canonical type.
-const Type *Type::getUnqualifiedDesugaredType() const {
+__attribute__((visibility("default"))) const Type *Type::getUnqualifiedDesugaredType() const {
   const Type *Cur = this;
 
   while (true) {
@@ -2302,7 +2302,7 @@ bool Type::hasUnsignedIntegerRepresentation() const {
   return isUnsignedIntegerOrEnumerationType();
 }
 
-bool Type::isFloatingType() const {
+__attribute__((visibility("default"))) bool Type::isFloatingType() const {
   if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->isFloatingPoint();
   if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
@@ -4227,7 +4227,7 @@ static TagDecl *getInterestingTagDecl(TagDecl *decl) {
   return decl;
 }
 
-TagDecl *TagType::getDecl() const { return getInterestingTagDecl(decl); }
+__attribute__((visibility("default"))) TagDecl *TagType::getDecl() const { return getInterestingTagDecl(decl); }
 
 bool TagType::isBeingDefined() const { return getDecl()->isBeingDefined(); }
 
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 2f110659d19a4..3402e274109cb 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -194,7 +194,7 @@ IncrementalCompilerBuilder::create(std::string TT,
   return CreateCI(**ErrOrCC1Args);
 }
 
-llvm::Expected<std::unique_ptr<CompilerInstance>>
+__attribute__((visibility("default"))) llvm::Expected<std::unique_ptr<CompilerInstance>>
 IncrementalCompilerBuilder::CreateCpp() {
   std::vector<const char *> Argv;
   Argv.reserve(5 + 1 + UserArgs.size());
@@ -524,7 +524,7 @@ const CompilerInstance *Interpreter::getCompilerInstance() const {
   return CI.get();
 }
 
-CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); }
+__attribute__((visibility("default"))) CompilerInstance *Interpreter::getCompilerInstance() { return CI.get(); }
 
 llvm::Expected<llvm::orc::LLJIT &> Interpreter::getExecutionEngine() {
   if (!IncrExecutor) {
@@ -577,7 +577,7 @@ Interpreter::RegisterPTU(TranslationUnitDecl *TU,
   return LastPTU;
 }
 
-llvm::Expected<PartialTranslationUnit &>
+__attribute__((visibility("default"))) llvm::Expected<PartialTranslationUnit &>
 Interpreter::Parse(llvm::StringRef Code) {
   // If we have a device parser, parse it first. The generated code will be
   // included in the host compilation
@@ -673,7 +673,7 @@ llvm::Error Interpreter::CreateExecutor() {
 
 void Interpreter::ResetExecutor() { IncrExecutor.reset(); }
 
-llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
+__attribute__((visibility("default"))) llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
   assert(T.TheModule);
   LLVM_DEBUG(
       llvm::dbgs() << "execute-ptu "
diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
index 3e7e32b2e8557..195de31155904 100644
--- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp
+++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
@@ -300,7 +300,7 @@ llvm::Expected<Expr *> Interpreter::ExtractValueFromExpr(Expr *E) {
 using namespace clang;
 
 // Temporary rvalue struct that need special care.
-REPL_EXTERNAL_VISIBILITY void *
+REPL_EXTERNAL_VISIBILITY __attribute__((visibility("default"))) void *
 __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal,
                                       void *OpaqueType) {
   Value &VRef = *(Value *)OutVal;
@@ -308,7 +308,7 @@ __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal,
   return VRef.getPtr();
 }
 
-extern "C" void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc(
+extern "C"  __attribute__((visibility("default"))) void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc(
     void *This, void *OutVal, void *OpaqueType, ...) {
   Value &VRef = *(Value *)OutVal;
   Interpreter *I = static_cast<Interpreter *>(This);
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index e8c65025bfe6d..965f8b096f64f 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11959,7 +11959,7 @@ EnumDecl *Sema::getStdAlignValT() const {
   return cast_or_null<EnumDecl>(StdAlignValT.get(Context.getExternalSource()));
 }
 
-NamespaceDecl *Sema::getStdNamespace() const {
+__attribute__((visibility("default"))) NamespaceDecl *Sema::getStdNamespace() const {
   return cast_or_null<NamespaceDecl>(
                                  StdNamespace.get(Context.getExternalSource()));
 }
diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h
index 0b8bb48b8fe5e..d124f44d72e94 100644
--- a/llvm/include/llvm/ADT/SmallVector.h
+++ b/llvm/include/llvm/ADT/SmallVector.h
@@ -73,7 +73,7 @@ template <class Size_T> class SmallVectorBase {
   /// This is an implementation of the grow() method which only works
   /// on POD-like data types and is out of line to reduce code duplication.
   /// This function will report a fatal error if it cannot increase capacity.
-  LLVM_ABI void grow_pod(void *FirstEl, size_t MinSize, size_t TSize);
+  __attribute__((visibility("default"))) LLVM_ABI void grow_pod(void *FirstEl, size_t MinSize, size_t TSize);
 
 public:
   size_t size() const { return Size; }
@@ -86,7 +86,7 @@ template <class Size_T> class SmallVectorBase {
   /// capacity for.
   ///
   /// This does not construct or destroy any elements in the vector.
-  void set_size(size_t N) {
+  __attribute__((visibility("default"))) void set_size(size_t N) {
     assert(N <= capacity()); // implies no overflow in assignment
     Size = static_cast<Size_T>(N);
   }
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index f87344e860518..ca8935c9e02e5 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -659,7 +659,7 @@ class raw_fd_stream : public raw_fd_ostream {
 /// raw_string_ostream operates without a buffer, delegating all memory
 /// management to the std::string. Thus the std::string is always up-to-date,
 /// may be used directly and there is no need to call flush().
-class LLVM_ABI raw_string_ostream : public raw_ostream {
+class __attribute__((visibility("default"))) LLVM_ABI raw_string_ostream : public raw_ostream {
   std::string &OS;
 
   /// See raw_ostream::write_impl.
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 954af7fff92a8..a4afa302725ae 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -104,7 +104,7 @@ void APInt::initFromArray(ArrayRef<uint64_t> bigVal) {
   clearUnusedBits();
 }
 
-APInt::APInt(unsigned numBits, ArrayRef<uint64_t> bigVal) : BitWidth(numBits) {
+__attribute__((visibility("default"))) APInt::APInt(unsigned numBits, ArrayRef<uint64_t> bigVal) : BitWidth(numBits) {
   initFromArray(bigVal);
 }
 
@@ -281,7 +281,7 @@ bool APInt::equalSlowCase(const APInt &RHS) const {
   return std::equal(U.pVal, U.pVal + getNumWords(), RHS.U.pVal);
 }
 
-int APInt::compare(const APInt& RHS) const {
+__attribute__((visibility("default"))) int APInt::compare(const APInt& RHS) const {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
   if (isSingleWord())
     return U.VAL < RHS.U.VAL ? -1 : U.VAL > RHS.U.VAL;
@@ -289,7 +289,7 @@ int APInt::compare(const APInt& RHS) const {
   return tcCompare(U.pVal, RHS.U.pVal, getNumWords());
 }
 
-int APInt::compareSigned(const APInt& RHS) const {
+__attribute__((visibility("default"))) int APInt::compareSigned(const APInt& RHS) const {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
   if (isSingleWord()) {
     int64_t lhsSext = SignExtend64(U.VAL, BitWidth);
@@ -982,7 +982,7 @@ APInt APInt::truncSSat(unsigned width) const {
 }
 
 // Sign extend to a new width.
-APInt APInt::sext(unsigned Width) const {
+__attribute__((visibility("default"))) APInt APInt::sext(unsigned Width) const {
   assert(Width >= BitWidth && "Invalid APInt SignExtend request");
 
   if (Width <= APINT_BITS_PER_WORD)
@@ -1009,7 +1009,7 @@ APInt APInt::sext(unsigned Width) const {
 }
 
 //  Zero extend to a new width.
-APInt APInt::zext(unsigned width) const {
+__attribute__((visibility("default"))) APInt APInt::zext(unsigned width) const {
   assert(width >= BitWidth && "Invalid APInt ZeroExtend request");
 
   if (width <= APINT_BITS_PER_WORD)
diff --git a/llvm/lib/Support/Debug.cpp b/llvm/lib/Support/Debug.cpp
index 5bb04d0c22998..7f85a0ceda01d 100644
--- a/llvm/lib/Support/Debug.cpp
+++ b/llvm/lib/Support/Debug.cpp
@@ -159,7 +159,7 @@ static void debug_user_sig_handler(void *Cookie) {
 }
 
 /// dbgs - Return a circular-buffered debug stream.
-raw_ostream &llvm::dbgs() {
+__attribute__((visibility("default"))) raw_ostream &llvm::dbgs() {
   // Do one-time initialization in a thread-safe way.
   static struct dbgstream {
     circular_raw_ostream strm;
diff --git a/llvm/lib/Support/Error.cpp b/llvm/lib/Support/Error.cpp
index d168b462a6eb2..13b66a581cc32 100644
--- a/llvm/lib/Support/Error.cpp
+++ b/llvm/lib/Support/Error.cpp
@@ -62,7 +62,7 @@ char ECError::ID = 0;
 char StringError::ID = 0;
 char FileError::ID = 0;
 
-void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {
+__attribute__((visibility("default"))) void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) {
   if (!E)
     return;
   OS << ErrorBanner;
@@ -125,7 +125,7 @@ std::error_code errorToErrorCode(Error Err) {
 }
 
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
-void Error::fatalUncheckedError() const {
+__attribute__((visibility("default"))) void Error::fatalUncheckedError() const {
   dbgs() << "Program aborted due to an unhandled Error:\n";
   if (getPtr()) {
     getPtr()->log(dbgs());
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index cc16f2037ea58..014622aa35dba 100644
--- a/llvm/lib/Support/ErrorHandling.cpp
+++ b/llvm/lib/Support/ErrorHandling.cpp
@@ -219,7 +219,7 @@ void llvm::install_out_of_memory_new_handler() {
 }
 #endif
 
-void llvm::llvm_unreachable_internal(const char *msg, const char *file,
+__attribute__((visibility("default"))) void llvm::llvm_unreachable_internal(const char *msg, const char *file,
                                      unsigned line) {
   // This code intentionally doesn't call the ErrorHandler callback, because
   // llvm_unreachable is intended to be used to indicate "impossible"
diff --git a/llvm/lib/Support/MemAlloc.cpp b/llvm/lib/Support/MemAlloc.cpp
index 6adc9abd75c5b..f671be4426abe 100644
--- a/llvm/lib/Support/MemAlloc.cpp
+++ b/llvm/lib/Support/MemAlloc.cpp
@@ -11,7 +11,7 @@
 
 // These are out of line to have __cpp_aligned_new not affect ABI.
 
-LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+__attribute__((visibility("default"))) LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
 llvm::allocate_buffer(size_t Size, size_t Alignment) {
   void *Result = ::operator new(Size,
 #ifdef __cpp_aligned_new
diff --git a/llvm/lib/Support/StringMap.cpp b/llvm/lib/Support/StringMap.cpp
index 432e1fc343f1f..aea9a6ae08d6c 100644
--- a/llvm/lib/Support/StringMap.cpp
+++ b/llvm/lib/Support/StringMap.cpp
@@ -43,7 +43,7 @@ static inline unsigned *getHashTable(StringMapEntryBase **TheTable,
   return reinterpret_cast<un...
[truncated]
 | 
    
| 
           
  | 
    
| 
          
 ✅ With the latest revision this PR passed the C/C++ code formatter.  | 
    
| 
           I didn't think about Windows when making this PR, and realised after the ci failure that I should be using LLVM_ABI since its defined as attribute((visibility("default"))) on Emscripten (see 
  | 
    
…being hidden when linking clangInterpreter library to other libraries during Emscripten build Currently CppInterOp links its Emscripten shared library to the Emscripten static library libclangInterpreter.a . Certain symbols get hidden in libclangInterOp.a due to the -fvisibility-inlines-hidden flag when building an Emscripten build of llvm. This causes the CppInterOp to have to manually export these in a non Emscripten recommended way (see https://github.com/compiler-research/CppInterOp/blob/main/lib/CppInterOp/exports.ld ). This patch would allow us to avoid this method, by marking these symbols are visible, instead of hidden.
4c5f7af    to
    d528fe6      
    Compare
  
    | 
           Can’t we solve this with a linker script provided externally when building llvm?  | 
    
| 
           @vgvassilev Emscripten doesn't support linker scripts, and that is the platform that has the issue.  | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm super confused by what you are doing here. Most of the symbols you are annotating here are not inline and shouldn't be affected by -fvisibility-inlines-hidden. Some of them have already been annotated as LLVM_ABI in the header (and some of them haven't because the annotation effort hasn't progressed to them yet). It sounds to me like you are actually building with -fvisibilty=hidden, which is not yet a supported configuration.
          
 Hi @nikic I worked out that was a troublesome flag, by removing it locally, and the symbols then appeared in the Emscripten shared library of CppInterOp, although the Emscripten shared library ended up very large, and unusable. I can also get them to appear in CppInterOp Emscripten shared library by building the Emscripten version of llvm using EMCC_CFLAGS="-fvisibilty=default" (EMCC_CFLAGS is an emsdk environment variable https://emscripten.org/docs/tools_reference/emcc.html#environment-variables) , but again the size of the Emscripten shared library ends up much bigger. Sorry, I missed where these that have already been annotated with LLVM_ABI. Can you help me out by pointing out an example? The llvm build I am doing is detailed here https://github.com/compiler-research/CppInterOp/blob/main/Emscripten-build-instructions.md . Also, this is separate to the issue to making a Windows Shared library issue here #109483 (this purely based on your comment that ' the annotation effort hasn't progressed to them yet')  | 
    
| 
           I have no idea how what I did caused the Flang test to fail.  | 
    
          
 That same work also enables building libLLVM/libclang with   | 
    
          
 It is not the default for Web Assembly as far as I understand based on WebAssembly/tool-conventions#176 (see line 'A long while ago we choose to make -fvisibility=hidden the default for the WebAssembly backend in llvm') and https://github.com/emscripten-core/emscripten/blob/b0c461c10482e12f88e192e04b3640acb1577f64/emcc.py#L203 (see 'even though the upstream backend defaults visibility=hidden'). @sbc100 will be able to say for certain.  | 
    
| 
           I think that it might be better to wait on this change until we do this properly. In the mean time, the workaround would be to use   | 
    
          
 I'll avoid using fvisibility=default and stick with he current export method, as using fvisibility=default globally increased the shared library size from an already big 45Mb to an even bigger for 66 Mb (me and @vgvassilev are hoping to find ways to reduce its size significantly, so using this flag would be a massive step back). Having the symbols annotated individually allowed CppInterOp to keep the same size. Hopefully with @andrurogerz work to annotate these interfaces, CppInterOps Emscripten shared library will automatically give the unexpected added benefit of these all these symbols becoming visible 😊  | 
    
@sbc100 Currently CppInterOp links its Emscripten shared library to the Emscripten static library libclangInterpreter.a . Certain symbols get hidden in libclangInterOp.a due to the -fvisibility-inlines-hidden flag when building an Emscripten build of llvm. This causes the CppInterOp to have to manually export these in a non Emscripten recommended way (see https://github.com/compiler-research/CppInterOp/blob/main/lib/CppInterOp/exports.ld ). This patch would allow us to avoid this method, by marking these symbols are visible, instead of hidden.
This may not be the best approach to stop these symbols being hidden during an Emscripten build of llvm, to avoid CppInterOps currently hacky approach to making them available after linking to libclangInterpreter.a, but this is the best I could come up with. I am open to other suggestions.
cc @vgvassilev