Browse Source

Generate valid C++ for specialisations with void

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
update-llvm
Dimitar Dobrev 4 years ago
parent
commit
a69f6d1d6d
  1. 47
      src/CppParser/Parser.cpp
  2. 2
      src/CppParser/Parser.h
  3. 5
      src/Generator/Generators/CSharp/CSharpSources.cs
  4. 2
      tests/CSharp/CSharpTemplates.cpp
  5. 20
      tests/CSharp/CSharpTemplates.h

47
src/CppParser/Parser.cpp

@ -2978,18 +2978,19 @@ static const clang::CodeGen::CGFunctionInfo& GetCodeGenFunctionInfo(
FTy.castAs<clang::FunctionProtoType>()); FTy.castAs<clang::FunctionProtoType>());
} }
bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty) bool Parser::CanCheckCodeGenInfo(const clang::Type* Ty)
{ {
auto FinalType = GetFinalType(Ty); auto FinalType = GetFinalType(Ty);
if (FinalType->isDependentType() || if (FinalType->isDependentType() ||
FinalType->isInstantiationDependentType() || FinalType->isUndeducedType()) FinalType->isInstantiationDependentType() ||
FinalType->isUndeducedType())
return false; return false;
if (FinalType->isFunctionType()) if (FinalType->isFunctionType())
{ {
auto FTy = FinalType->getAs<clang::FunctionType>(); auto FTy = FinalType->getAs<clang::FunctionType>();
auto CanCheck = CanCheckCodeGenInfo(S, FTy->getReturnType().getTypePtr()); auto CanCheck = CanCheckCodeGenInfo(FTy->getReturnType().getTypePtr());
if (!CanCheck) if (!CanCheck)
return false; return false;
@ -2998,7 +2999,7 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
auto FPTy = FinalType->getAs<clang::FunctionProtoType>(); auto FPTy = FinalType->getAs<clang::FunctionProtoType>();
for (const auto& ParamType : FPTy->getParamTypes()) for (const auto& ParamType : FPTy->getParamTypes())
{ {
auto CanCheck = CanCheckCodeGenInfo(S, ParamType.getTypePtr()); auto CanCheck = CanCheckCodeGenInfo(ParamType.getTypePtr());
if (!CanCheck) if (!CanCheck)
return false; return false;
} }
@ -3015,7 +3016,8 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
{ {
if (auto MPT = Ty->getAs<clang::MemberPointerType>()) if (auto MPT = Ty->getAs<clang::MemberPointerType>())
if (!MPT->isDependentType()) if (!MPT->isDependentType())
S.RequireCompleteType(clang::SourceLocation(), clang::QualType(Ty, 0), 1); c->getSema().RequireCompleteType(clang::SourceLocation(),
clang::QualType(Ty, 0), 1);
} }
return true; return true;
@ -3088,7 +3090,7 @@ void Parser::InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* C
if (!CTS->isCompleteDefinition()) if (!CTS->isCompleteDefinition())
{ {
c->getSema().InstantiateClassTemplateSpecialization(CTS->getBeginLoc(), c->getSema().InstantiateClassTemplateSpecialization(CTS->getBeginLoc(),
CTS, TSK_ImplicitInstantiation, false); CTS, clang::TemplateSpecializationKind::TSK_ImplicitInstantiation, false);
} }
for (auto Decl : CTS->decls()) for (auto Decl : CTS->decls())
@ -3101,7 +3103,7 @@ void Parser::InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* C
{ {
c->getSema().InstantiateClass(Nested->getBeginLoc(), Nested, Template, c->getSema().InstantiateClass(Nested->getBeginLoc(), Nested, Template,
MultiLevelTemplateArgumentList(CTS->getTemplateArgs()), MultiLevelTemplateArgumentList(CTS->getTemplateArgs()),
TSK_ImplicitInstantiation, false); clang::TemplateSpecializationKind::TSK_ImplicitInstantiation, false);
} }
} }
} }
@ -3210,7 +3212,8 @@ void Parser::MarkValidity(Function* F)
auto FD = static_cast<FunctionDecl*>(F->originalPtr); auto FD = static_cast<FunctionDecl*>(F->originalPtr);
if (!FD->getTemplateInstantiationPattern() || !FD->isExternallyVisible()) if (!FD->isImplicit() &&
(!FD->getTemplateInstantiationPattern() || !FD->isExternallyVisible()))
return; return;
auto existingClient = c->getSema().getDiagnostics().getClient(); auto existingClient = c->getSema().getDiagnostics().getClient();
@ -3230,6 +3233,18 @@ void Parser::MarkValidity(Function* F)
F->isInvalid = IsInvalid(FD->getBody(), Bodies); F->isInvalid = IsInvalid(FD->getBody(), Bodies);
} }
if (!F->isInvalid)
{
DeclContext* Context = FD->getDeclContext();
while (Context)
{
F->isInvalid = cast<Decl>(Context)->isInvalidDecl();
if (F->isInvalid)
break;
Context = Context->getParent();
}
}
c->getSema().getDiagnostics().setClient(existingClient, false); c->getSema().getDiagnostics().setClient(existingClient, false);
c->getSema().TUScope = nullptr; c->getSema().TUScope = nullptr;
} }
@ -3332,14 +3347,11 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
ParamStartLoc = VD->getEndLoc(); ParamStartLoc = VD->getEndLoc();
} }
if (!opts->skipFunctionBodies) if (!opts->skipFunctionBodies && FD->hasBody())
{
if (FD->hasBody())
{ {
if (auto Body = FD->getBody()) if (auto Body = FD->getBody())
F->bodyStmt = WalkStatement(Body); F->bodyStmt = WalkStatement(Body);
} }
}
auto& CXXABI = codeGenTypes->getCXXABI(); auto& CXXABI = codeGenTypes->getCXXABI();
bool HasThisReturn = false; bool HasThisReturn = false;
@ -3355,15 +3367,17 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
if (auto FTSI = FD->getTemplateSpecializationInfo()) if (auto FTSI = FD->getTemplateSpecializationInfo())
F->specializationInfo = WalkFunctionTemplateSpec(FTSI, F); F->specializationInfo = WalkFunctionTemplateSpec(FTSI, F);
MarkValidity(F);
F->qualifiedType = GetQualifiedType(FD->getType(), &FTL);
const CXXMethodDecl* MD; const CXXMethodDecl* MD;
if (FD->isDependentContext() || if (FD->isDependentContext() ||
((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() && ((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() &&
!HasLayout(cast<CXXRecordDecl>(MD->getDeclContext()))) || !HasLayout(cast<CXXRecordDecl>(MD->getDeclContext()))) ||
!CanCheckCodeGenInfo(c->getSema(), FD->getReturnType().getTypePtr()) || !CanCheckCodeGenInfo(FD->getReturnType().getTypePtr()) ||
std::any_of(FD->parameters().begin(), FD->parameters().end(), std::any_of(FD->parameters().begin(), FD->parameters().end(),
[this](auto* P) { return !CanCheckCodeGenInfo(c->getSema(), P->getType().getTypePtr()); })) [this](auto* P) { return !CanCheckCodeGenInfo(P->getType().getTypePtr()); }))
{ {
F->qualifiedType = GetQualifiedType(FD->getType(), &FTL);
return; return;
} }
@ -3377,9 +3391,6 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
F->Parameters[Index++]->isIndirect = F->Parameters[Index++]->isIndirect =
Arg.info.isIndirect() && !Arg.info.getIndirectByVal(); Arg.info.isIndirect() && !Arg.info.getIndirectByVal();
} }
MarkValidity(F);
F->qualifiedType = GetQualifiedType(FD->getType(), &FTL);
} }
Function* Parser::WalkFunction(const clang::FunctionDecl* FD) Function* Parser::WalkFunction(const clang::FunctionDecl* FD)

2
src/CppParser/Parser.h

@ -135,7 +135,7 @@ private:
bool IsValidDeclaration(const clang::SourceLocation& Loc); bool IsValidDeclaration(const clang::SourceLocation& Loc);
std::string GetDeclMangledName(const clang::Decl* D); std::string GetDeclMangledName(const clang::Decl* D);
std::string GetTypeName(const clang::Type* Type); std::string GetTypeName(const clang::Type* Type);
bool CanCheckCodeGenInfo(clang::Sema & S, const clang::Type * Ty); bool CanCheckCodeGenInfo(const clang::Type* Ty);
void CompleteIfSpecializationType(const clang::QualType& QualType); void CompleteIfSpecializationType(const clang::QualType& QualType);
void InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* CTS); void InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* CTS);
Parameter* WalkParameter(const clang::ParmVarDecl* PVD, Parameter* WalkParameter(const clang::ParmVarDecl* PVD,

5
src/Generator/Generators/CSharp/CSharpSources.cs

@ -365,7 +365,10 @@ namespace CppSharp.Generators.CSharp
if (dependentClass.HasDependentValueFieldInLayout()) if (dependentClass.HasDependentValueFieldInLayout())
return specializedClasses.KeepSingleAllPointersSpecialization(); return specializedClasses.KeepSingleAllPointersSpecialization();
return new[] { specializedClasses.FirstOrDefault(s => s.IsGenerated) ?? return new[] {
specializedClasses.FirstOrDefault(
s => s.IsGenerated && s.Classes.All(c => !c.IsIncomplete)) ??
specializedClasses.FirstOrDefault(s => s.IsGenerated) ??
specializedClasses.First()}; specializedClasses.First()};
} }

2
tests/CSharp/CSharpTemplates.cpp

@ -120,7 +120,7 @@ void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool>
{ {
} }
void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii) void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii, Base<void> _24)
{ {
} }

20
tests/CSharp/CSharpTemplates.h

@ -195,9 +195,27 @@ template <typename T>
class Base class Base
{ {
public: public:
class Nested
{
public:
void f(const T& t);
friend void f(Nested& n) {}
};
void invokeFriend();
typedef T* typedefT; typedef T* typedefT;
}; };
template <typename T>
void Base<T>::Nested::f(const T& t)
{
}
template <typename T>
void Base<T>::invokeFriend()
{
f(Nested());
}
template <typename T> template <typename T>
class DependentValueFields : public Base<T> class DependentValueFields : public Base<T>
{ {
@ -844,7 +862,7 @@ void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool>
VirtualDependentValueFields<float> _22, VirtualDependentValueFields<const char*> _23, VirtualDependentValueFields<float> _22, VirtualDependentValueFields<const char*> _23,
std::string s); std::string s);
void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii); void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii, Base<void> _24);
std::map<int, int> usesValidSpecialisationOfIgnoredTemplate(); std::map<int, int> usesValidSpecialisationOfIgnoredTemplate();

Loading…
Cancel
Save