23#define WARNMSG "; exporting skipped!"
27 clang::Visibility g_DefaultTypeVisibility = clang::DefaultVisibility;
28 clang::Visibility g_DefaultValueVisibility = clang::DefaultVisibility;
30 bool ShouldExport(clang::Sema& sema,
const clang::NamedDecl* decl)
35 auto& diag = sema.getDiagnostics();
36 const auto invalidVisibility = diag.getCustomDiagID(
37 clang::DiagnosticsEngine::Warning,
38 "declaration cannot be exported because of its visibility" WARNMSG);
39 const auto invalidAccess = diag.getCustomDiagID(
40 clang::DiagnosticsEngine::Warning,
41 "non-public declaration cannot be exported" WARNMSG);
42 const auto invalidSignature = sema.getDiagnostics().getCustomDiagID(
43 clang::DiagnosticsEngine::Warning,
44 "%0 function '%1' cannot be exported" WARNMSG);
49 if (
const auto vis = decl->getExplicitVisibility(clang::isa<clang::RecordDecl>(decl)
50 ? clang::TypeDecl::VisibilityForType
51 : clang::TypeDecl::VisibilityForValue);
52 (vis.has_value() && vis != clang::DefaultVisibility) ||
53 (clang::isa<clang::RecordDecl>(decl)
54 ? g_DefaultTypeVisibility
55 : g_DefaultValueVisibility) != clang::DefaultVisibility)
57 sema.Diag(decl->getLocation(), invalidVisibility);
64 if (
const auto fn = clang::dyn_cast<clang::FunctionDecl>(decl))
66 if (fn->isConsteval() || fn->isConstexpr())
68 sema.Diag(fn->getDefaultLoc(), invalidSignature) <<
"consteval/constexpr" << decl;
73 sema.Diag(fn->getDefaultLoc(), invalidSignature) <<
"variadic" << decl;
78 sema.Diag(fn->getDefaultLoc(), invalidSignature) <<
"deleted" << decl;
83 sema.Diag(fn->getDefaultLoc(), invalidSignature) <<
"inlined" << decl;
86 if (fn->isPureVirtual())
88 sema.Diag(fn->getDefaultLoc(), invalidSignature) <<
"pure-virtual" << decl;
96 auto record = clang::dyn_cast<clang::CXXRecordDecl>(decl->getDeclContext());
100 auto access = clang::AS_none;
101 for (
auto* member: record->decls())
103 if (clang::isa<clang::AccessSpecDecl>(member))
104 access = clang::cast<clang::AccessSpecDecl>(member)->getAccess();
105 if (clang::declaresSameEntity(member, decl))
109 if (access == clang::AS_public ||
110 (record->isStruct() && access == clang::AS_none))
113 sema.Diag(decl->getLocation(), invalidAccess);
124 static constexpr Spelling S[] = {
125 { clang::ParsedAttr::AS_GNU,
"__lilac_export" },
126 { clang::ParsedAttr::AS_Declspec,
"__lilac_export" },
127 { clang::ParsedAttr::AS_C23,
"__lilac_export" },
128 { clang::ParsedAttr::AS_C23,
"lilac::export" },
129 { clang::ParsedAttr::AS_CXX11,
"__lilac_export" },
130 { clang::ParsedAttr::AS_CXX11,
"lilac::export" },
138 const clang::ParsedAttr& attr,
139 const clang::Decl* decl)
const
144 if (!clang::isa<clang::FunctionDecl>(decl) &&
145 !clang::isa<clang::RecordDecl>(decl) &&
146 !clang::isa<clang::EnumDecl>(decl))
148 const auto invalidDeclType = sema.getDiagnostics().getCustomDiagID(
149 clang::DiagnosticsEngine::Warning,
150 "'%0' attribute can be applied to only functions, enumerations and records" WARNMSG);
152 sema.Diag(attr.getLoc(), invalidDeclType) << attr;
155 if (!ShouldExport(sema, clang::cast<clang::NamedDecl>(decl)))
164 const clang::ParsedAttr& attr)
const
166 if (attr.getNumArgs())
168 const auto anyArgs = sema.getDiagnostics().getCustomDiagID(
169 clang::DiagnosticsEngine::Warning,
170 "'%0' attribute accepts no argument" WARNMSG);
171 sema.Diag(attr.getLoc(), anyArgs) << attr;
172 return AttributeNotApplied;
175 if (
auto*
const tag = clang::dyn_cast<clang::TagDecl>(decl))
177 tag->addAttr(clang::AnnotateTypeAttr::Create(sema.Context,
AttrMangling,
nullptr, 0));
179 else if (
auto*
const function = clang::dyn_cast<clang::FunctionDecl>(decl))
181 function->addAttr(clang::AnnotateAttr::Create(sema.Context,
AttrMangling,
nullptr, 0));
185 assert(
false &&
"invalid decl type");
188 return AttributeApplied;
193 g_DefaultTypeVisibility = LO.getTypeVisibilityMode();
194 g_DefaultValueVisibility = LO.getValueVisibilityMode();
200static clang::ParsedAttrInfoRegistry::Add<lilac::cxx::ExportAttrInfo> X(
"apiexport",
"");
bool diagAppertainsToDecl(clang::Sema &sema, const clang::ParsedAttr &attr, const clang::Decl *decl) const override
bool acceptsLangOpts(const clang::LangOptions &LO) const override
AttrHandling handleDeclAttribute(clang::Sema &sema, clang::Decl *decl, const clang::ParsedAttr &attr) const override
static constexpr std::string AttrMangling