Browse Source

Adds clang 19 support (#1949)

* Initial commit supporting Clang 19

* Fixes link errors. Fixes for failing tests

* Fixes failing macOS lib test

* Free disk space in LLVM CI.

* Free disk space in Ubuntu and macOS CI jobs.

* Format new code.

---------

Co-authored-by: Christopher Franzwa <chris@vergeaero.com>
main
João Matos 1 week ago committed by GitHub
parent
commit
8f2f92ba2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 27
      .github/workflows/llvm.yml
  2. 24
      .github/workflows/main.yml
  3. 7
      build/LLVM.lua
  4. 2
      build/llvm/LLVM-commit
  5. 6
      build/llvm/LLVM.lua
  6. 8
      src/CppParser/ASTNameMangler.cpp
  7. 287
      src/CppParser/Comments.cpp
  8. 4
      src/CppParser/Link.cpp
  9. 2
      src/CppParser/ParseExpr.cpp
  10. 146
      src/CppParser/Parser.cpp
  11. 4
      src/CppParser/Parser.h

27
.github/workflows/llvm.yml

@ -25,6 +25,33 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
- run: df -h
- name: Free Disk Space
if: startsWith(matrix.os, 'ubuntu')
uses: endersonmenezes/free-disk-space@v2
with:
remove_android: true
remove_dotnet: true
remove_haskell: true
remove_tool_cache: true
remove_swap: true
remove_packages: "azure-cli google-cloud-cli microsoft-edge-stable google-chrome-stable firefox postgresql* temurin-* *llvm* mysql* dotnet-sdk-*"
remove_packages_one_command: true
remove_folders: "/usr/share/swift /usr/share/miniconda /usr/share/az* /usr/local/lib/node_modules /usr/local/share/chromium /usr/local/share/powershell /usr/local/julia /usr/local/aws-cli /usr/local/aws-sam-cli /usr/share/gradle"
testing: false
- name: Free Disk Space
if: startsWith(matrix.os, 'macos')
run: |
sudo rm -rf /Library/Frameworks/Mono.framework
sudo rm -rf /Library/Frameworks/Xamarin.iOS.framework
sudo rm -rf /Library/Frameworks/Xamarin.Android.framework
sudo rm -rf /Users/runner/Library/Android
sudo rm -rf /usr/local/share/powershell
sudo find /Applications -type d -name "Xcode_*.app" ! -name "Xcode_$XCODE_VERSION.app" -prune -exec rm -rf "{}" \;
- run: df -h
- name: Install cross compilers - name: Install cross compilers
if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.platform, 'arm64') if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.platform, 'arm64')
run: sudo apt install -y g++-aarch64-linux-gnu gcc-aarch64-linux-gnu run: sudo apt install -y g++-aarch64-linux-gnu gcc-aarch64-linux-gnu

24
.github/workflows/main.yml

@ -38,6 +38,30 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Free Disk Space
if: startsWith(matrix.os, 'ubuntu')
uses: endersonmenezes/free-disk-space@v2
with:
remove_android: true
remove_haskell: true
remove_tool_cache: true
remove_swap: true
remove_packages: "azure-cli google-cloud-cli microsoft-edge-stable google-chrome-stable firefox postgresql* temurin-* *llvm* mysql* dotnet-sdk-*"
remove_packages_one_command: true
remove_folders: "/usr/share/swift /usr/share/miniconda /usr/share/az* /usr/local/lib/node_modules /usr/local/share/chromium /usr/local/share/powershell /usr/local/julia /usr/local/aws-cli /usr/local/aws-sam-cli /usr/share/gradle"
testing: false
- name: Free Disk Space
if: startsWith(matrix.os, 'macos')
run: |
sudo rm -rf /Library/Frameworks/Mono.framework
sudo rm -rf /Library/Frameworks/Xamarin.iOS.framework
sudo rm -rf /Library/Frameworks/Xamarin.Android.framework
sudo rm -rf /Users/runner/Library/Android
sudo rm -rf /usr/local/share/powershell
sudo find /Applications -type d -name "Xcode_*.app" ! -name "Xcode_$XCODE_VERSION.app" -prune -exec rm -rf "{}" \;
- run: df -h
- name: Setup emsdk - name: Setup emsdk
uses: pyodide/setup-emsdk@v15 uses: pyodide/setup-emsdk@v15
with: with:

7
build/LLVM.lua

@ -137,7 +137,8 @@ function SetupLLVMLibs()
filter { "toolset:msc*" } filter { "toolset:msc*" }
links { "version" } links { "version" }
links { "ntdll"}
filter {} filter {}
if LLVMDirPerConfiguration then if LLVMDirPerConfiguration then
@ -164,6 +165,7 @@ function SetupLLVMLibs()
links links
{ {
"clangAPINotes",
"clangFrontend", "clangFrontend",
"clangDriver", "clangDriver",
"clangSerialization", "clangSerialization",
@ -185,8 +187,10 @@ function SetupLLVMLibs()
"LLVMPasses", "LLVMPasses",
"LLVMObjCARCOpts", "LLVMObjCARCOpts",
"LLVMLibDriver", "LLVMLibDriver",
"LLVMFrontendOffloading",
"LLVMFrontendHLSL", "LLVMFrontendHLSL",
"LLVMFrontendOpenMP", "LLVMFrontendOpenMP",
"LLVMHipStdPar",
"LLVMOption", "LLVMOption",
"LLVMCoverage", "LLVMCoverage",
"LLVMCoroutines", "LLVMCoroutines",
@ -201,6 +205,7 @@ function SetupLLVMLibs()
"LLVMAArch64Disassembler", "LLVMAArch64Disassembler",
"LLVMAArch64Info", "LLVMAArch64Info",
"LLVMAArch64Utils", "LLVMAArch64Utils",
"LLVMFrontendDriver",
"LLVMipo", "LLVMipo",
"LLVMInstrumentation", "LLVMInstrumentation",
"LLVMVectorize", "LLVMVectorize",

2
build/llvm/LLVM-commit

@ -1 +1 @@
6eb36aed86ea276695697093eb8136554c29286b cd708029e0b2869e80abe31ddb175f7c35361f90

6
build/llvm/LLVM.lua

@ -263,6 +263,7 @@ function cmake(gen, conf, builddir, options)
.. ' -DLLVM_INCLUDE_TESTS=false' .. ' -DLLVM_INCLUDE_TESTS=false'
.. ' -DLLVM_ENABLE_LIBEDIT=false' .. ' -DLLVM_ENABLE_LIBEDIT=false'
.. ' -DLLVM_ENABLE_LIBXML2=false' .. ' -DLLVM_ENABLE_LIBXML2=false'
.. ' -DLLVM_ENABLE_MLGO=false'
.. ' -DLLVM_ENABLE_TERMINFO=false' .. ' -DLLVM_ENABLE_TERMINFO=false'
.. ' -DLLVM_ENABLE_ZLIB=false' .. ' -DLLVM_ENABLE_ZLIB=false'
.. ' -DLLVM_ENABLE_ZSTD=false' .. ' -DLLVM_ENABLE_ZSTD=false'
@ -326,7 +327,7 @@ function cmake(gen, conf, builddir, options)
.. ' -DLLVM_TOOL_LLVM_MODEXTRACT_BUILD=false' .. ' -DLLVM_TOOL_LLVM_MODEXTRACT_BUILD=false'
.. ' -DLLVM_TOOL_LLVM_MT_BUILD=false' .. ' -DLLVM_TOOL_LLVM_MT_BUILD=false'
.. ' -DLLVM_TOOL_LLVM_NM_BUILD=false' .. ' -DLLVM_TOOL_LLVM_NM_BUILD=false'
.. ' -DLLVM_TOOL_LLVM_OBJCOPY_BUILD=false' .. ' -DLLVM_TOOL_LLVM_OBJCOPY_BUILD=true'
.. ' -DLLVM_TOOL_LLVM_OBJDUMP_BUILD=false' .. ' -DLLVM_TOOL_LLVM_OBJDUMP_BUILD=false'
.. ' -DLLVM_TOOL_LLVM_OPT_FUZZER_BUILD=false' .. ' -DLLVM_TOOL_LLVM_OPT_FUZZER_BUILD=false'
.. ' -DLLVM_TOOL_LLVM_OPT_REPORT_BUILD=false' .. ' -DLLVM_TOOL_LLVM_OPT_REPORT_BUILD=false'
@ -366,7 +367,8 @@ function cmake(gen, conf, builddir, options)
.. ' -DLLVM_TOOL_VERIFY_USELISTORDER_BUILD=false' .. ' -DLLVM_TOOL_VERIFY_USELISTORDER_BUILD=false'
.. ' -DLLVM_TOOL_VFABI_DEMANGLE_FUZZER_BUILD=false' .. ' -DLLVM_TOOL_VFABI_DEMANGLE_FUZZER_BUILD=false'
.. ' -DLLVM_TOOL_XCODE_TOOLCHAIN_BUILD=false' .. ' -DLLVM_TOOL_XCODE_TOOLCHAIN_BUILD=false'
.. ' -DLLVM_TOOL_YAML2OBJ_BUILD=false' .. ' -DLLVM_TOOL_YAML2OBJ_BUILD=true'
.. ' -DLLVM_TOOL_LLVM_OBJCOPY_BUILD=true'
.. ' -DLLVM_HAVE_LIBXAR=false' .. ' -DLLVM_HAVE_LIBXAR=false'
.. ' -DCLANG_BUILD_EXAMPLES=false ' .. ' -DCLANG_BUILD_EXAMPLES=false '
.. ' -DCLANG_BUILD_TOOLS=false' .. ' -DCLANG_BUILD_TOOLS=false'

8
src/CppParser/ASTNameMangler.cpp

@ -99,14 +99,18 @@ std::string ASTNameMangler::GetMangledStructor(const NamedDecl* ND, unsigned Str
return FrontendBuf; return FrontendBuf;
} }
std::string ASTNameMangler::GetMangledThunk(const CXXMethodDecl* MD, const ThunkInfo& T, bool /*ElideOverrideInfo*/) const std::string ASTNameMangler::GetMangledThunk(const CXXMethodDecl* MD, const ThunkInfo& T, bool ElideOverrideInfo) const
{ {
std::string FrontendBuf; std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf); llvm::raw_string_ostream FOS(FrontendBuf);
// TODO: Enable `ElideOverrideInfo` param if clang is updated to 19 // TODO: Enable `ElideOverrideInfo` param if clang is updated to 19
MC->mangleThunk(MD, T, /*ElideOverrideInfo,*/ FOS);
#if LLVM_VERSION_MAJOR >= 19
MC->mangleThunk(MD, T, ElideOverrideInfo, FOS);
#else
MC->mangleThunk(MD, T, FOS);
#endif
return FrontendBuf; return FrontendBuf;
} }

287
src/CppParser/Comments.cpp

@ -49,41 +49,22 @@ RawComment* Parser::WalkRawComment(const clang::RawComment* RC)
} }
static InlineCommandComment::RenderKind static InlineCommandComment::RenderKind
ConvertRenderKind(clang::comments::InlineCommandComment::RenderKind Kind) ConvertRenderKind(std::string Kind)
{ {
using namespace clang::comments; using namespace clang::comments;
switch (Kind) if (Kind == "b")
{ return AST::InlineCommandComment::RenderKind::RenderBold;
case clang::comments::InlineCommandComment::RenderNormal: else if (Kind == "c")
return CppSharp::CppParser::AST::InlineCommandComment::RenderKind::RenderNormal; return AST::InlineCommandComment::RenderKind::RenderMonospaced;
case clang::comments::InlineCommandComment::RenderBold: else if (Kind == "a")
return CppSharp::CppParser::AST::InlineCommandComment::RenderKind::RenderBold; return AST::InlineCommandComment::RenderKind::RenderAnchor;
case clang::comments::InlineCommandComment::RenderMonospaced: else if (Kind == "e")
return CppSharp::CppParser::AST::InlineCommandComment::RenderKind::RenderMonospaced; return AST::InlineCommandComment::RenderKind::RenderEmphasized;
case clang::comments::InlineCommandComment::RenderEmphasized: else
return CppSharp::CppParser::AST::InlineCommandComment::RenderKind::RenderEmphasized; return AST::InlineCommandComment::RenderKind::RenderNormal;
case clang::comments::InlineCommandComment::RenderAnchor:
return CppSharp::CppParser::AST::InlineCommandComment::RenderKind::RenderAnchor;
}
llvm_unreachable("Unknown render kind"); llvm_unreachable("Unknown render kind");
} }
static ParamCommandComment::PassDirection
ConvertParamPassDirection(clang::comments::ParamCommandComment::PassDirection Dir)
{
using namespace clang::comments;
switch (Dir)
{
case clang::comments::ParamCommandComment::In:
return CppSharp::CppParser::AST::ParamCommandComment::PassDirection::In;
case clang::comments::ParamCommandComment::Out:
return CppSharp::CppParser::AST::ParamCommandComment::PassDirection::Out;
case clang::comments::ParamCommandComment::InOut:
return CppSharp::CppParser::AST::ParamCommandComment::PassDirection::InOut;
}
llvm_unreachable("Unknown parameter pass direction");
}
static void HandleInlineContent(const clang::comments::InlineContentComment* CK, static void HandleInlineContent(const clang::comments::InlineContentComment* CK,
InlineContentComment* IC) InlineContentComment* IC)
{ {
@ -102,158 +83,120 @@ static void HandleBlockCommand(const clang::comments::BlockCommandComment* CK,
} }
} }
static Comment* ConvertCommentBlock(clang::comments::Comment* C) static Comment* ConvertCommentBlock(clang::comments::Comment* C, clang::CompilerInstance* CI)
{ {
using namespace clang; using namespace clang;
using clang::comments::Comment; using clang::comments::Comment;
// This needs to have an underscore else we get an ICE under VS2012. // This needs to have an underscore else we get an ICE under VS2012.
CppSharp::CppParser::AST::Comment* _Comment = 0; CppSharp::CppParser::AST::Comment* _Comment = nullptr;
auto kind = C->getCommentKind();
switch (C->getCommentKind()) if (auto CK = dyn_cast<const comments::FullComment>(C))
{ {
case Comment::FullCommentKind: auto FC = new FullComment();
{ _Comment = FC;
auto CK = cast<clang::comments::FullComment>(C); for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
auto FC = new FullComment(); FC->Blocks.push_back(static_cast<BlockContentComment*>(ConvertCommentBlock(*I, CI)));
_Comment = FC; }
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I) else if (auto CK = dyn_cast<const comments::ParamCommandComment>(C))
{ {
auto Content = ConvertCommentBlock(*I); auto PC = new ParamCommandComment();
FC->Blocks.push_back(static_cast<BlockContentComment*>(Content)); _Comment = PC;
} HandleBlockCommand(CK, PC);
break; if (CK->isParamIndexValid() && !CK->isVarArgParam())
} PC->paramIndex = CK->getParamIndex();
case Comment::BlockCommandCommentKind: PC->paragraphComment = static_cast<ParagraphComment*>(ConvertCommentBlock(CK->getParagraph(), CI));
{ }
auto CK = cast<const clang::comments::BlockCommandComment>(C); else if (auto CK = dyn_cast<const comments::TParamCommandComment>(C))
auto BC = new BlockCommandComment(); {
_Comment = BC; auto TC = new TParamCommandComment();
HandleBlockCommand(CK, BC); _Comment = TC;
BC->paragraphComment = static_cast<ParagraphComment*>(ConvertCommentBlock(CK->getParagraph())); HandleBlockCommand(CK, TC);
break; if (CK->isPositionValid())
} for (unsigned I = 0, E = CK->getDepth(); I != E; ++I)
case Comment::ParamCommandCommentKind: TC->Position.push_back(CK->getIndex(I));
{ TC->paragraphComment = static_cast<ParagraphComment*>(ConvertCommentBlock(CK->getParagraph(), CI));
auto CK = cast<clang::comments::ParamCommandComment>(C); }
auto PC = new ParamCommandComment(); else if (auto CK = dyn_cast<const comments::VerbatimBlockComment>(C))
_Comment = PC; {
HandleBlockCommand(CK, PC); auto VB = new VerbatimBlockComment();
PC->direction = ConvertParamPassDirection(CK->getDirection()); _Comment = VB;
if (CK->isParamIndexValid() && !CK->isVarArgParam()) for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
PC->paramIndex = CK->getParamIndex(); VB->Lines.push_back(static_cast<VerbatimBlockLineComment*>(ConvertCommentBlock(*I, CI)));
PC->paragraphComment = static_cast<ParagraphComment*>(ConvertCommentBlock(CK->getParagraph())); }
break; else if (auto CK = dyn_cast<const comments::VerbatimLineComment>(C))
} {
case Comment::TParamCommandCommentKind: auto VL = new VerbatimLineComment();
{ _Comment = VL;
auto CK = cast<clang::comments::TParamCommandComment>(C); VL->text = CK->getText().str();
_Comment = new TParamCommandComment(); }
auto TC = new TParamCommandComment(); else if (auto CK = dyn_cast<const comments::BlockCommandComment>(C))
_Comment = TC; {
HandleBlockCommand(CK, TC); auto BC = new BlockCommandComment();
if (CK->isPositionValid()) _Comment = BC;
for (unsigned I = 0, E = CK->getDepth(); I != E; ++I) HandleBlockCommand(CK, BC);
TC->Position.push_back(CK->getIndex(I)); BC->paragraphComment = static_cast<ParagraphComment*>(ConvertCommentBlock(CK->getParagraph(), CI));
TC->paragraphComment = static_cast<ParagraphComment*>(ConvertCommentBlock(CK->getParagraph())); }
break; else if (auto CK = dyn_cast<const comments::ParagraphComment>(C))
} {
case Comment::VerbatimBlockCommentKind: auto PC = new ParagraphComment();
{ _Comment = PC;
auto CK = cast<clang::comments::VerbatimBlockComment>(C); for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
auto VB = new VerbatimBlockComment(); PC->Content.push_back(static_cast<InlineContentComment*>(ConvertCommentBlock(*I, CI)));
_Comment = VB; PC->isWhitespace = CK->isWhitespace();
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I) }
{ else if (auto CK = dyn_cast<const comments::HTMLStartTagComment>(C))
auto Line = ConvertCommentBlock(*I); {
VB->Lines.push_back(static_cast<VerbatimBlockLineComment*>(Line)); auto TC = new HTMLStartTagComment();
} _Comment = TC;
break; HandleInlineContent(CK, TC);
} TC->tagName = CK->getTagName().str();
case Comment::VerbatimLineCommentKind: for (unsigned I = 0, E = CK->getNumAttrs(); I != E; ++I)
{
auto CK = cast<clang::comments::VerbatimLineComment>(C);
auto VL = new VerbatimLineComment();
_Comment = VL;
VL->text = CK->getText().str();
break;
}
case Comment::ParagraphCommentKind:
{
auto CK = cast<clang::comments::ParagraphComment>(C);
auto PC = new ParagraphComment();
_Comment = PC;
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I)
{
auto Content = ConvertCommentBlock(*I);
PC->Content.push_back(static_cast<InlineContentComment*>(Content));
}
PC->isWhitespace = CK->isWhitespace();
break;
}
case Comment::HTMLStartTagCommentKind:
{
auto CK = cast<clang::comments::HTMLStartTagComment>(C);
auto TC = new HTMLStartTagComment();
_Comment = TC;
HandleInlineContent(CK, TC);
TC->tagName = CK->getTagName().str();
for (unsigned I = 0, E = CK->getNumAttrs(); I != E; ++I)
{
auto A = CK->getAttr(I);
auto Attr = HTMLStartTagComment::Attribute();
Attr.name = A.Name.str();
Attr.value = A.Value.str();
TC->Attributes.push_back(Attr);
}
break;
}
case Comment::HTMLEndTagCommentKind:
{
auto CK = cast<clang::comments::HTMLEndTagComment>(C);
auto TC = new HTMLEndTagComment();
_Comment = TC;
HandleInlineContent(CK, TC);
TC->tagName = CK->getTagName().str();
break;
}
case Comment::TextCommentKind:
{
auto CK = cast<clang::comments::TextComment>(C);
auto TC = new TextComment();
_Comment = TC;
HandleInlineContent(CK, TC);
TC->text = CK->getText().str();
break;
}
case Comment::InlineCommandCommentKind:
{ {
auto CK = cast<clang::comments::InlineCommandComment>(C); auto A = CK->getAttr(I);
auto IC = new InlineCommandComment(); auto Attr = HTMLStartTagComment::Attribute();
_Comment = IC; Attr.name = A.Name.str();
HandleInlineContent(CK, IC); Attr.value = A.Value.str();
IC->commandId = CK->getCommandID(); TC->Attributes.push_back(Attr);
IC->commentRenderKind = ConvertRenderKind(CK->getRenderKind());
for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I)
{
auto Arg = InlineCommandComment::Argument();
Arg.text = CK->getArgText(I).str();
IC->Arguments.push_back(Arg);
}
break;
} }
case Comment::VerbatimBlockLineCommentKind: }
else if (auto CK = dyn_cast<const comments::HTMLEndTagComment>(C))
{
auto TC = new HTMLEndTagComment();
_Comment = TC;
HandleInlineContent(CK, TC);
TC->tagName = CK->getTagName().str();
}
else if (auto CK = dyn_cast<const comments::TextComment>(C))
{
auto TC = new TextComment();
_Comment = TC;
HandleInlineContent(CK, TC);
TC->text = CK->getText().str();
}
else if (auto CK = dyn_cast<const comments::InlineCommandComment>(C))
{
auto IC = new InlineCommandComment();
_Comment = IC;
HandleInlineContent(CK, IC);
IC->commandId = CK->getCommandID();
IC->commentRenderKind = ConvertRenderKind(CK->getCommandName(CI->getASTContext().getCommentCommandTraits()).str());
for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I)
{ {
auto CK = cast<clang::comments::VerbatimBlockLineComment>(C); auto Arg = InlineCommandComment::Argument();
auto VL = new VerbatimBlockLineComment(); Arg.text = CK->getArgText(I).str();
_Comment = VL; IC->Arguments.push_back(Arg);
VL->text = CK->getText().str();
break;
} }
case Comment::NoCommentKind: return nullptr;
default:
llvm_unreachable("Unknown comment kind");
} }
else if (auto CK = dyn_cast<const comments::VerbatimBlockLineComment>(C))
{
auto VL = new VerbatimBlockLineComment();
_Comment = VL;
VL->text = CK->getText().str();
}
else
llvm_unreachable("Unknown comment kind");
assert(_Comment && "Invalid comment instance"); assert(_Comment && "Invalid comment instance");
return _Comment; return _Comment;
@ -272,7 +215,7 @@ void Parser::HandleComments(const clang::Decl* D, Declaration* Decl)
if (clang::comments::FullComment* FC = RC->parse(c->getASTContext(), &c->getPreprocessor(), D)) if (clang::comments::FullComment* FC = RC->parse(c->getASTContext(), &c->getPreprocessor(), D))
{ {
auto CB = static_cast<FullComment*>(ConvertCommentBlock(FC)); auto CB = static_cast<FullComment*>(ConvertCommentBlock(FC, c.get()));
RawComment->fullCommentBlock = CB; RawComment->fullCommentBlock = CB;
} }
} }

4
src/CppParser/Link.cpp

@ -70,9 +70,9 @@ bool Parser::LinkWindows(const CppLinkerOptions* LinkerOptions,
} }
const Triple& Triple = c->getTarget().getTriple(); const Triple& Triple = c->getTarget().getTriple();
driver::Driver D("", Triple.str(), c->getDiagnostics()); clang::driver::Driver D("", Triple.str(), c->getDiagnostics());
opt::InputArgList Args(0, 0); opt::InputArgList Args(0, 0);
driver::toolchains::MSVCToolChain TC(D, Triple, Args); clang::driver::toolchains::MSVCToolChain TC(D, Triple, Args);
std::vector<std::string> LibraryPaths; std::vector<std::string> LibraryPaths;
LibraryPaths.push_back("-libpath:" + TC.getSubDirectoryPath( LibraryPaths.push_back("-libpath:" + TC.getSubDirectoryPath(

2
src/CppParser/ParseExpr.cpp

@ -2322,7 +2322,7 @@ AST::Expr* Parser::WalkExpression(const clang::Expr* Expr)
_S->hasExplicitTemplateArgs = S->hasExplicitTemplateArgs(); _S->hasExplicitTemplateArgs = S->hasExplicitTemplateArgs();
_S->numTemplateArgs = S->getNumTemplateArgs(); _S->numTemplateArgs = S->getNumTemplateArgs();
_S->requiresADL = S->requiresADL(); _S->requiresADL = S->requiresADL();
_S->isOverloaded = S->isOverloaded(); _S->isOverloaded = S->getNumDecls() > 1;
_Expr = _S; _Expr = _S;
break; break;
} }

146
src/CppParser/Parser.cpp

@ -17,6 +17,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <llvm/TargetParser/Host.h> #include <llvm/TargetParser/Host.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/Path.h> #include <llvm/Support/Path.h>
#include <llvm/Support/raw_ostream.h> #include <llvm/Support/raw_ostream.h>
#include <llvm/Support/TargetSelect.h> #include <llvm/Support/TargetSelect.h>
@ -36,6 +37,7 @@
#include <clang/AST/Comment.h> #include <clang/AST/Comment.h>
#include <clang/AST/DeclFriend.h> #include <clang/AST/DeclFriend.h>
#include <clang/AST/ExprCXX.h> #include <clang/AST/ExprCXX.h>
#include "clang/AST/TemplateBase.h"
#include <clang/CodeGen/CodeGenAction.h> #include <clang/CodeGen/CodeGenAction.h>
#include <clang/Lex/DirectoryLookup.h> #include <clang/Lex/DirectoryLookup.h>
#include <clang/Lex/HeaderSearch.h> #include <clang/Lex/HeaderSearch.h>
@ -1097,15 +1099,15 @@ static TagKind ConvertToTagKind(clang::TagTypeKind AS)
{ {
switch (AS) switch (AS)
{ {
case clang::TagTypeKind::TTK_Struct: case clang::TagTypeKind::Struct:
return TagKind::Struct; return TagKind::Struct;
case clang::TagTypeKind::TTK_Interface: case clang::TagTypeKind::Interface:
return TagKind::Interface; return TagKind::Interface;
case clang::TagTypeKind::TTK_Union: case clang::TagTypeKind::Union:
return TagKind::Union; return TagKind::Union;
case clang::TagTypeKind::TTK_Class: case clang::TagTypeKind::Class:
return TagKind::Class; return TagKind::Class;
case clang::TagTypeKind::TTK_Enum: case clang::TagTypeKind::Enum:
return TagKind::Enum; return TagKind::Enum;
} }
@ -1394,12 +1396,10 @@ Parser::WalkClassTemplateSpecialization(const clang::ClassTemplateSpecialization
CT->Specializations.push_back(TS); CT->Specializations.push_back(TS);
auto& TAL = CTS->getTemplateArgs(); auto& TAL = CTS->getTemplateArgs();
auto TSI = CTS->getTypeAsWritten(); auto TSI = CTS->getTemplateArgsAsWritten();
if (TSI) if (TSI)
{ {
auto TL = TSI->getTypeLoc(); TS->Arguments = WalkTemplateArgumentList(&TAL, TSI);
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>();
TS->Arguments = WalkTemplateArgumentList(&TAL, &TSL);
} }
else else
{ {
@ -1449,11 +1449,14 @@ Parser::WalkClassTemplatePartialSpecialization(const clang::ClassTemplatePartial
CT->Specializations.push_back(TS); CT->Specializations.push_back(TS);
auto& TAL = CTS->getTemplateArgs(); auto& TAL = CTS->getTemplateArgs();
if (auto TSI = CTS->getTypeAsWritten()) auto TSI = CTS->getTemplateArgsAsWritten();
if (TSI)
{ {
auto TL = TSI->getTypeLoc(); TS->Arguments = WalkTemplateArgumentList(&TAL, TSI);
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>(); }
TS->Arguments = WalkTemplateArgumentList(&TAL, &TSL); else
{
TS->Arguments = WalkTemplateArgumentList(&TAL, (TemplateSpecializationTypeLoc*)0);
} }
if (CTS->isCompleteDefinition()) if (CTS->isCompleteDefinition())
@ -1567,7 +1570,11 @@ TypeTemplateParameter* Parser::WalkTypeTemplateParameter(const clang::TemplateTy
HandleDeclaration(TTPD, TP); HandleDeclaration(TTPD, TP);
if (TTPD->hasDefaultArgument()) if (TTPD->hasDefaultArgument())
TP->defaultArgument = GetQualifiedType(TTPD->getDefaultArgument()); {
auto TSI = TTPD->getDefaultArgument().getTypeSourceInfo();
if (TSI)
TP->defaultArgument = GetQualifiedType(TSI->getType());
}
TP->depth = TTPD->getDepth(); TP->depth = TTPD->getDepth();
TP->index = TTPD->getIndex(); TP->index = TTPD->getIndex();
TP->isParameterPack = TTPD->isParameterPack(); TP->isParameterPack = TTPD->isParameterPack();
@ -1591,7 +1598,7 @@ NonTypeTemplateParameter* Parser::WalkNonTypeTemplateParameter(const clang::NonT
HandleDeclaration(NTTPD, NTP); HandleDeclaration(NTTPD, NTP);
if (NTTPD->hasDefaultArgument()) if (NTTPD->hasDefaultArgument())
NTP->defaultArgument = WalkExpressionObsolete(NTTPD->getDefaultArgument()); NTP->defaultArgument = WalkExpressionObsolete(NTTPD->getDefaultArgument().getSourceExpression());
NTP->type = GetQualifiedType(NTTPD->getType()); NTP->type = GetQualifiedType(NTTPD->getType());
NTP->depth = NTTPD->getDepth(); NTP->depth = NTTPD->getDepth();
NTP->index = NTTPD->getIndex(); NTP->index = NTTPD->getIndex();
@ -1641,6 +1648,40 @@ std::vector<TemplateArgument> Parser::WalkTemplateArgumentList(const clang::Temp
//-----------------------------------// //-----------------------------------//
template <typename TypeLoc>
std::vector<TemplateArgument> Parser::WalkTemplateArgumentList(
llvm::ArrayRef<clang::TemplateArgument> TAL,
TypeLoc* TSTL)
{
using namespace clang;
const bool LocValid = TSTL && !TSTL->isNull() && TSTL->getTypePtr();
std::vector<AST::TemplateArgument> params;
const size_t typeLocNumArgs = LocValid ? TSTL->getNumArgs() : 0;
for (size_t i = 0, e = TAL.size(); i < e; ++i)
{
const clang::TemplateArgument& TA = TAL[i];
TemplateArgumentLoc TArgLoc;
TemplateArgumentLoc* ArgLoc = nullptr;
if (i < typeLocNumArgs && e == typeLocNumArgs)
{
TArgLoc = TSTL->getArgLoc(i);
ArgLoc = &TArgLoc;
}
auto Arg = WalkTemplateArgument(TA, ArgLoc);
params.push_back(Arg);
}
return params;
}
//-----------------------------------//
std::vector<TemplateArgument> std::vector<TemplateArgument>
Parser::WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, Parser::WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL,
const clang::ASTTemplateArgumentListInfo* TALI) const clang::ASTTemplateArgumentListInfo* TALI)
@ -1893,7 +1934,7 @@ Parser::WalkVarTemplateSpecialization(const clang::VarTemplateSpecializationDecl
VT->Specializations.push_back(TS); VT->Specializations.push_back(TS);
auto& TAL = VTS->getTemplateArgs(); auto& TAL = VTS->getTemplateArgs();
auto TSI = VTS->getTypeAsWritten(); auto TSI = VTS->getTypeSourceInfo();
if (TSI) if (TSI)
{ {
auto TL = TSI->getTypeLoc(); auto TL = TSI->getTypeLoc();
@ -1933,7 +1974,7 @@ Parser::WalkVarTemplatePartialSpecialization(const clang::VarTemplatePartialSpec
VT->Specializations.push_back(TS); VT->Specializations.push_back(TS);
auto& TAL = VTS->getTemplateArgs(); auto& TAL = VTS->getTemplateArgs();
if (auto TSI = VTS->getTypeAsWritten()) if (auto TSI = VTS->getTypeSourceInfo())
{ {
auto TL = TSI->getTypeLoc(); auto TL = TSI->getTypeLoc();
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>(); auto TSL = TL.getAs<TemplateSpecializationTypeLoc>();
@ -2812,11 +2853,9 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
if (TS->isSugared()) if (TS->isSugared())
TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL); TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL);
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments());
if (!LocValid) if (!LocValid)
{ {
TST->Arguments = WalkTemplateArgumentList(&TArgs, (TemplateSpecializationTypeLoc*)nullptr); TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), (TemplateSpecializationTypeLoc*)nullptr);
Ty = TST; Ty = TST;
break; break;
} }
@ -2840,21 +2879,21 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
case TypeLoc::DependentTemplateSpecialization: case TypeLoc::DependentTemplateSpecialization:
{ {
DependentTemplateSpecializationTypeLoc TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>(); DependentTemplateSpecializationTypeLoc TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL); TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), &TSpecTL);
Ty = TST; Ty = TST;
break; break;
} }
case TypeLoc::TemplateSpecialization: case TypeLoc::TemplateSpecialization:
{ {
TemplateSpecializationTypeLoc TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>(); TemplateSpecializationTypeLoc TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL); TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), &TSpecTL);
Ty = TST; Ty = TST;
break; break;
} }
case TypeLoc::TemplateTypeParm: case TypeLoc::TemplateTypeParm:
{ {
TemplateTypeParmTypeLoc TTPTL = TL->getAs<TemplateTypeParmTypeLoc>(); TemplateTypeParmTypeLoc TTPTL = TL->getAs<TemplateTypeParmTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, (TemplateSpecializationTypeLoc*)nullptr); TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), (TemplateSpecializationTypeLoc*)nullptr);
break; break;
} }
default: default:
@ -2873,11 +2912,9 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
if (TS->isSugared()) if (TS->isSugared())
TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL); TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL);
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments());
if (!LocValid) if (!LocValid)
{ {
TST->Arguments = WalkTemplateArgumentList(&TArgs, (DependentTemplateSpecializationTypeLoc*)nullptr); TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), (DependentTemplateSpecializationTypeLoc*)nullptr);
Ty = TST; Ty = TST;
break; break;
} }
@ -2901,18 +2938,18 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
case TypeLoc::DependentTemplateSpecialization: case TypeLoc::DependentTemplateSpecialization:
{ {
DependentTemplateSpecializationTypeLoc TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>(); DependentTemplateSpecializationTypeLoc TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL); TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), &TSpecTL);
break; break;
} }
case TypeLoc::TemplateSpecialization: case TypeLoc::TemplateSpecialization:
{ {
TemplateSpecializationTypeLoc TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>(); TemplateSpecializationTypeLoc TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>();
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL); TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), &TSpecTL);
break; break;
} }
case TypeLoc::TemplateTypeParm: case TypeLoc::TemplateTypeParm:
{ {
TST->Arguments = WalkTemplateArgumentList(&TArgs, (DependentTemplateSpecializationTypeLoc*)nullptr); TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), (DependentTemplateSpecializationTypeLoc*)nullptr);
break; break;
} }
default: default:
@ -3510,7 +3547,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
F->isConstExpr = FD->isConstexpr(); F->isConstExpr = FD->isConstexpr();
F->isVariadic = FD->isVariadic(); F->isVariadic = FD->isVariadic();
F->isDependent = FD->isDependentContext(); F->isDependent = FD->isDependentContext();
F->isPure = FD->isPure(); F->isPure = FD->isPureVirtual();
F->isDeleted = FD->isDeleted(); F->isDeleted = FD->isDeleted();
F->isDefaulted = FD->isDefaulted(); F->isDefaulted = FD->isDefaulted();
SetBody(FD, F); SetBody(FD, F);
@ -4476,7 +4513,6 @@ Declaration* Parser::WalkDeclaration(const clang::Decl* D)
break; break;
} }
case Decl::BuiltinTemplate: case Decl::BuiltinTemplate:
case Decl::ClassScopeFunctionSpecialization:
case Decl::PragmaComment: case Decl::PragmaComment:
case Decl::PragmaDetectMismatch: case Decl::PragmaDetectMismatch:
case Decl::Empty: case Decl::Empty:
@ -4614,31 +4650,31 @@ void Parser::SetupLLVMCodegen()
} }
bool Parser::SetupSourceFiles(const std::vector<std::string>& SourceFiles, bool Parser::SetupSourceFiles(const std::vector<std::string>& SourceFiles,
std::vector<const clang::FileEntry*>& FileEntries) std::vector<clang::OptionalFileEntryRef>& FileEntries)
{ {
// Check that the file is reachable. clang::ConstSearchDirIterator* Dir = nullptr;
clang::ConstSearchDirIterator* Dir = 0; llvm::ArrayRef<std::pair<clang::OptionalFileEntryRef, clang::DirectoryEntryRef>> EmptyIncluders;
llvm::ArrayRef<std::pair<const clang::FileEntry*, clang::DirectoryEntryRef>> Includers;
for (const auto& SourceFile : SourceFiles) for (const auto& SourceFile : SourceFiles)
{ {
auto FileEntry = c->getPreprocessor().getHeaderSearchInfo().LookupFile(SourceFile, auto FileEntry = c->getPreprocessor().getHeaderSearchInfo().LookupFile(
clang::SourceLocation(), /*isAngled*/ true, SourceFile,
nullptr, Dir, Includers, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); clang::SourceLocation(),
/*isAngled*/ true,
nullptr, Dir,
EmptyIncluders,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
if (!FileEntry) if (!FileEntry)
return false; return false;
FileEntries.push_back(&FileEntry.getPointer()->getFileEntry()); FileEntries.push_back(FileEntry);
} }
// Create a virtual file that includes the header. This gets rid of some
// Clang warnings about parsing an header file as the main file.
std::string source; std::string source;
for (const auto& SourceFile : SourceFiles) for (const auto& SourceFile : SourceFiles)
{ {
source += "#include \"" + SourceFile + "\"" + "\n"; source += "#include \"" + SourceFile + "\"\n";
} }
source += "\0"; source += "\0";
@ -4652,7 +4688,7 @@ bool Parser::SetupSourceFiles(const std::vector<std::string>& SourceFiles,
class SemaConsumer : public clang::SemaConsumer class SemaConsumer : public clang::SemaConsumer
{ {
public: public:
SemaConsumer(Parser& parser, std::vector<const clang::FileEntry*>& entries) SemaConsumer(Parser& parser, std::vector<clang::OptionalFileEntryRef>& entries)
: Parser(parser) : Parser(parser)
, FileEntries(entries) , FileEntries(entries)
{ {
@ -4662,7 +4698,7 @@ public:
private: private:
Parser& Parser; Parser& Parser;
std::vector<const clang::FileEntry*>& FileEntries; std::vector<clang::OptionalFileEntryRef>& FileEntries;
}; };
void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx) void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx)
@ -4675,7 +4711,7 @@ void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx)
Parser.HandleDeclaration(TU, Unit); Parser.HandleDeclaration(TU, Unit);
if (Unit->originalPtr == nullptr) if (Unit->originalPtr == nullptr)
Unit->originalPtr = (void*)FileEntry; Unit->originalPtr = (void*)&FileEntry->getFileEntry();
Parser.WalkAST(TU); Parser.WalkAST(TU);
} }
@ -4695,7 +4731,7 @@ ParserResult* Parser::Parse(const std::vector<std::string>& SourceFiles)
Setup(); Setup();
SetupLLVMCodegen(); SetupLLVMCodegen();
std::vector<const clang::FileEntry*> FileEntries; std::vector<clang::OptionalFileEntryRef> FileEntries;
if (!SetupSourceFiles(SourceFiles, FileEntries)) if (!SetupSourceFiles(SourceFiles, FileEntries))
{ {
res->kind = ParserResultKind::FileNotFound; res->kind = ParserResultKind::FileNotFound;
@ -4829,7 +4865,7 @@ ParserResultKind Parser::ParseSharedLib(const std::string& File,
for (const auto& ImportedSymbol : COFFObjectFile->import_directories()) for (const auto& ImportedSymbol : COFFObjectFile->import_directories())
{ {
llvm::StringRef Name; llvm::StringRef Name;
if (!ImportedSymbol.getName(Name) && (Name.endswith(".dll") || Name.endswith(".DLL"))) if (!ImportedSymbol.getName(Name) && (Name.ends_with(".dll") || Name.ends_with(".DLL")))
NativeLib->Dependencies.push_back(Name.str()); NativeLib->Dependencies.push_back(Name.str());
} }
@ -4857,12 +4893,18 @@ ParserResultKind Parser::ParseSharedLib(const std::string& File,
// see https://bugs.llvm.org/show_bug.cgi?id=44433 // see https://bugs.llvm.org/show_bug.cgi?id=44433
for (const auto& Symbol : MachOObjectFile->symbols()) for (const auto& Symbol : MachOObjectFile->symbols())
{ {
if (Symbol.getName().takeError() || Symbol.getFlags().takeError()) auto NameOrErr = Symbol.getName();
auto FlagsOrErr = Symbol.getFlags();
if (!NameOrErr || !FlagsOrErr)
return ParserResultKind::Error; return ParserResultKind::Error;
if ((Symbol.getFlags().get() & llvm::object::BasicSymbolRef::Flags::SF_Exported) && auto Flags = *FlagsOrErr;
!(Symbol.getFlags().get() & llvm::object::BasicSymbolRef::Flags::SF_Undefined)) if ((Flags & llvm::object::BasicSymbolRef::SF_Exported) &&
NativeLib->Symbols.push_back(Symbol.getName().get().str()); !(Flags & llvm::object::BasicSymbolRef::SF_Undefined))
{
NativeLib->Symbols.push_back(NameOrErr->str());
}
} }
return ParserResultKind::Success; return ParserResultKind::Success;
} }

4
src/CppParser/Parser.h

@ -70,7 +70,7 @@ namespace CppSharp { namespace CppParser {
void SetupLLVMCodegen(); void SetupLLVMCodegen();
bool SetupSourceFiles(const std::vector<std::string>& SourceFiles, bool SetupSourceFiles(const std::vector<std::string>& SourceFiles,
std::vector<const clang::FileEntry*>& FileEntries); std::vector<clang::OptionalFileEntryRef>& FileEntries);
bool IsSupported(const clang::NamedDecl* ND); bool IsSupported(const clang::NamedDecl* ND);
bool IsSupported(const clang::CXXMethodDecl* MD); bool IsSupported(const clang::CXXMethodDecl* MD);
@ -114,6 +114,8 @@ namespace CppSharp { namespace CppParser {
WalkVarTemplatePartialSpecialization(const clang::VarTemplatePartialSpecializationDecl* VTS); WalkVarTemplatePartialSpecialization(const clang::VarTemplatePartialSpecializationDecl* VTS);
template <typename TypeLoc> template <typename TypeLoc>
std::vector<AST::TemplateArgument> WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, TypeLoc* TSTL); std::vector<AST::TemplateArgument> WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, TypeLoc* TSTL);
template <typename TypeLoc>
std::vector<AST::TemplateArgument> WalkTemplateArgumentList(llvm::ArrayRef<clang::TemplateArgument> TAL, TypeLoc* TSTL);
std::vector<AST::TemplateArgument> WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, const clang::ASTTemplateArgumentListInfo* TSTL); std::vector<AST::TemplateArgument> WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, const clang::ASTTemplateArgumentListInfo* TSTL);
void WalkVTable(const clang::CXXRecordDecl* RD, AST::Class* C); void WalkVTable(const clang::CXXRecordDecl* RD, AST::Class* C);
AST::QualifiedType GetQualifiedType(clang::QualType qual, const clang::TypeLoc* TL = 0); AST::QualifiedType GetQualifiedType(clang::QualType qual, const clang::TypeLoc* TL = 0);

Loading…
Cancel
Save