Browse Source

Completed just class template specialisations used in functions.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/991/merge
Dimitar Dobrev 8 years ago
parent
commit
feb2df8fae
  1. 155
      src/CppParser/Parser.cpp
  2. 2
      src/CppParser/Parser.h
  3. 2
      src/Generator.Tests/AST/TestAST.cs

155
src/CppParser/Parser.cpp

@ -1111,6 +1111,45 @@ WalkTemplateSpecializationKind(clang::TemplateSpecializationKind Kind) @@ -1111,6 +1111,45 @@ WalkTemplateSpecializationKind(clang::TemplateSpecializationKind Kind)
llvm_unreachable("Unknown template specialization kind");
}
//-----------------------------------//
struct Diagnostic
{
clang::SourceLocation Location;
llvm::SmallString<100> Message;
clang::DiagnosticsEngine::Level Level;
};
struct DiagnosticConsumer : public clang::DiagnosticConsumer
{
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level Level,
const clang::Diagnostic& Info) override {
// Update the base type NumWarnings and NumErrors variables.
if (Level == clang::DiagnosticsEngine::Warning)
NumWarnings++;
if (Level == clang::DiagnosticsEngine::Error ||
Level == clang::DiagnosticsEngine::Fatal)
{
NumErrors++;
if (Decl)
{
Decl->setInvalidDecl();
Decl = 0;
}
}
auto Diag = Diagnostic();
Diag.Location = Info.getLocation();
Diag.Level = Level;
Info.FormatDiagnostic(Diag.Message);
Diagnostics.push_back(Diag);
}
std::vector<Diagnostic> Diagnostics;
clang::Decl* Decl;
};
ClassTemplateSpecialization*
Parser::WalkClassTemplateSpecialization(const clang::ClassTemplateSpecializationDecl* CTS)
{
@ -2110,39 +2149,6 @@ static const clang::Type* GetFinalType(const clang::Type* Ty) @@ -2110,39 +2149,6 @@ static const clang::Type* GetFinalType(const clang::Type* Ty)
}
}
bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid)
{
auto FinalType = GetFinalType(QualType.getTypePtr());
if (auto Tag = FinalType->getAsTagDecl())
{
if (auto CTS = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(Tag))
{
// we cannot get a location in some cases of template arguments
if (!LocValid || CTS->isCompleteDefinition())
return false;
auto TAL = &CTS->getTemplateArgs();
for (size_t i = 0; i < TAL->size(); i++)
{
auto TA = TAL->get(i);
if (TA.getKind() == clang::TemplateArgument::ArgKind::Type)
{
auto Type = TA.getAsType();
if (Type->isVoidType())
return false;
}
}
auto Unit = GetTranslationUnit(Tag);
// HACK: completing all system types overflows the managed stack
// while running the AST converter since the latter is a giant indirect recursion
// this solution is a hack because we might need to complete system template specialisations
// such as std:string or std::vector in order to represent them in the target language
return !Unit->isSystemHeader;
}
}
return false;
}
Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
bool DesugarType)
{
@ -2153,11 +2159,6 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, @@ -2153,11 +2159,6 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
auto LocValid = TL && !TL->isNull();
auto CompleteType = ShouldCompleteType(QualType, LocValid);
if (CompleteType)
c->getSema().RequireCompleteType(
LocValid ? TL->getLocStart() : clang::SourceLocation(), QualType, 1);
const clang::Type* Type = QualType.getTypePtr();
if (DesugarType)
@ -2857,8 +2858,8 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty) @@ -2857,8 +2858,8 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
{
auto FinalType = GetFinalType(Ty);
if (Ty->isDependentType() || FinalType->isDependentType() ||
FinalType->isInstantiationDependentType())
if (FinalType->isDependentType() ||
FinalType->isInstantiationDependentType() || FinalType->isUndeducedType())
return false;
if (auto RT = FinalType->getAs<clang::RecordType>())
@ -2899,6 +2900,27 @@ static clang::TypeLoc DesugarTypeLoc(const clang::TypeLoc& Loc) @@ -2899,6 +2900,27 @@ static clang::TypeLoc DesugarTypeLoc(const clang::TypeLoc& Loc)
return Loc;
}
void Parser::CompleteIfSpecializationType(const clang::QualType& QualType)
{
using namespace clang;
auto Type = QualType->getUnqualifiedDesugaredType();
auto RD = Type->getAsCXXRecordDecl();
if (!RD)
RD = const_cast<CXXRecordDecl*>(Type->getPointeeCXXRecordDecl());
ClassTemplateSpecializationDecl* CTS;
if (!RD ||
!(CTS = llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)) ||
CTS->isCompleteDefinition())
return;
auto Diagnostics = c->getSema().getDiagnostics().getClient();
auto SemaDiagnostics = static_cast<::DiagnosticConsumer*>(Diagnostics);
SemaDiagnostics->Decl = CTS;
c->getSema().InstantiateClassTemplateSpecialization(CTS->getLocStart(),
CTS, TSK_ImplicitInstantiation, false);
}
Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD,
const clang::SourceLocation& ParamStartLoc)
{
@ -2913,14 +2935,18 @@ Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD, @@ -2913,14 +2935,18 @@ Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD,
TypeLoc PTL;
if (auto TSI = PVD->getTypeSourceInfo())
PTL = PVD->getTypeSourceInfo()->getTypeLoc();
PTL = TSI->getTypeLoc();
auto paramRange = PVD->getSourceRange();
paramRange.setBegin(ParamStartLoc);
HandlePreprocessedEntities(P, paramRange, MacroLocation::FunctionParameters);
P->qualifiedType = GetQualifiedType(PVD->getOriginalType(), &PTL);
const auto& Type = PVD->getOriginalType();
auto Function = PVD->getParentFunctionOrMethod();
if (Function && cast<NamedDecl>(Function)->isExternallyVisible())
CompleteIfSpecializationType(Type);
P->qualifiedType = GetQualifiedType(Type, &PTL);
P->hasDefaultValue = PVD->hasDefaultArg();
P->index = PVD->getFunctionScopeIndex();
if (PVD->hasDefaultArg() && !PVD->hasUnparsedDefaultArg())
@ -3008,8 +3034,11 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F, @@ -3008,8 +3034,11 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
}
else
F->qualifiedType = GetQualifiedType(FD->getType());
F->returnType = GetQualifiedType(FD->getReturnType(), &RTL);
auto ReturnType = FD->getReturnType();
if (FD->isExternallyVisible())
CompleteIfSpecializationType(ReturnType);
F->returnType = GetQualifiedType(ReturnType, &RTL);
const auto& Mangled = GetDeclMangledName(FD);
F->mangled = Mangled;
@ -3047,7 +3076,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F, @@ -3047,7 +3076,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
if (GetDeclText(Range, Sig))
F->signature = Sig;
for (const auto& VD : FD->parameters())
for (auto VD : FD->parameters())
{
auto P = WalkParameter(VD, ParamStartLoc);
F->Parameters.push_back(P);
@ -3069,6 +3098,9 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F, @@ -3069,6 +3098,9 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
if (auto FTSI = FD->getTemplateSpecializationInfo())
F->specializationInfo = WalkFunctionTemplateSpec(FTSI, F);
if (F->isDependent)
return;
const CXXMethodDecl* MD;
if ((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() &&
!HasLayout(cast<CXXRecordDecl>(MD->getDeclContext())))
@ -3874,39 +3906,6 @@ Declaration* Parser::WalkDeclaration(const clang::Decl* D) @@ -3874,39 +3906,6 @@ Declaration* Parser::WalkDeclaration(const clang::Decl* D)
return Decl;
}
//-----------------------------------//
struct Diagnostic
{
clang::SourceLocation Location;
llvm::SmallString<100> Message;
clang::DiagnosticsEngine::Level Level;
};
struct DiagnosticConsumer : public clang::DiagnosticConsumer
{
virtual ~DiagnosticConsumer() { }
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level Level,
const clang::Diagnostic& Info) override {
// Update the base type NumWarnings and NumErrors variables.
if (Level == clang::DiagnosticsEngine::Warning)
NumWarnings++;
if (Level == clang::DiagnosticsEngine::Error ||
Level == clang::DiagnosticsEngine::Fatal)
NumErrors++;
auto Diag = Diagnostic();
Diag.Location = Info.getLocation();
Diag.Level = Level;
Info.FormatDiagnostic(Diag.Message);
Diagnostics.push_back(Diag);
}
std::vector<Diagnostic> Diagnostics;
};
void Parser::HandleDiagnostics(ParserResult* res)
{
auto DiagClient = (DiagnosticConsumer&) c->getDiagnosticClient();

2
src/CppParser/Parser.h

@ -87,7 +87,6 @@ private: @@ -87,7 +87,6 @@ private:
void WalkVariable(const clang::VarDecl* VD, Variable* Var);
Friend* WalkFriend(const clang::FriendDecl* FD);
RawComment* WalkRawComment(const clang::RawComment* RC);
bool ShouldCompleteType(const clang::QualType& QualType, bool LocValid);
Type* WalkType(clang::QualType QualType, const clang::TypeLoc* TL = 0,
bool DesugarType = false);
TemplateArgument WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc);
@ -124,6 +123,7 @@ private: @@ -124,6 +123,7 @@ private:
std::string GetDeclMangledName(const clang::Decl* D);
std::string GetTypeName(const clang::Type* Type);
bool CanCheckCodeGenInfo(clang::Sema & S, const clang::Type * Ty);
void CompleteIfSpecializationType(const clang::QualType& QualType);
Parameter* WalkParameter(const clang::ParmVarDecl* PVD,
const clang::SourceLocation& ParamStartLoc);
void SetBody(const clang::FunctionDecl* FD, Function* F);

2
src/Generator.Tests/AST/TestAST.cs

@ -282,7 +282,7 @@ namespace CppSharp.Generator.Tests.AST @@ -282,7 +282,7 @@ namespace CppSharp.Generator.Tests.AST
Assert.AreEqual(5, template.Specializations.Count);
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[0].SpecializationKind);
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[3].SpecializationKind);
Assert.AreEqual(TemplateSpecializationKind.ImplicitInstantiation, template.Specializations[4].SpecializationKind);
Assert.AreEqual(TemplateSpecializationKind.Undeclared, template.Specializations[4].SpecializationKind);
var typeDef = AstContext.FindTypedef("TestTemplateClassInt").FirstOrDefault();
Assert.IsNotNull(typeDef, "Couldn't find TestTemplateClassInt typedef.");
var integerInst = typeDef.Type as TemplateSpecializationType;

Loading…
Cancel
Save