Browse Source

Completed just class template specialisations used in functions.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/991/merge
Dimitar Dobrev 9 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)
llvm_unreachable("Unknown template specialization 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* ClassTemplateSpecialization*
Parser::WalkClassTemplateSpecialization(const clang::ClassTemplateSpecializationDecl* CTS) Parser::WalkClassTemplateSpecialization(const clang::ClassTemplateSpecializationDecl* CTS)
{ {
@ -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, Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
bool DesugarType) bool DesugarType)
{ {
@ -2153,11 +2159,6 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
auto LocValid = TL && !TL->isNull(); 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(); const clang::Type* Type = QualType.getTypePtr();
if (DesugarType) if (DesugarType)
@ -2857,8 +2858,8 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
{ {
auto FinalType = GetFinalType(Ty); auto FinalType = GetFinalType(Ty);
if (Ty->isDependentType() || FinalType->isDependentType() || if (FinalType->isDependentType() ||
FinalType->isInstantiationDependentType()) FinalType->isInstantiationDependentType() || FinalType->isUndeducedType())
return false; return false;
if (auto RT = FinalType->getAs<clang::RecordType>()) if (auto RT = FinalType->getAs<clang::RecordType>())
@ -2899,6 +2900,27 @@ static clang::TypeLoc DesugarTypeLoc(const clang::TypeLoc& Loc)
return 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, Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD,
const clang::SourceLocation& ParamStartLoc) const clang::SourceLocation& ParamStartLoc)
{ {
@ -2913,14 +2935,18 @@ Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD,
TypeLoc PTL; TypeLoc PTL;
if (auto TSI = PVD->getTypeSourceInfo()) if (auto TSI = PVD->getTypeSourceInfo())
PTL = PVD->getTypeSourceInfo()->getTypeLoc(); PTL = TSI->getTypeLoc();
auto paramRange = PVD->getSourceRange(); auto paramRange = PVD->getSourceRange();
paramRange.setBegin(ParamStartLoc); paramRange.setBegin(ParamStartLoc);
HandlePreprocessedEntities(P, paramRange, MacroLocation::FunctionParameters); 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->hasDefaultValue = PVD->hasDefaultArg();
P->index = PVD->getFunctionScopeIndex(); P->index = PVD->getFunctionScopeIndex();
if (PVD->hasDefaultArg() && !PVD->hasUnparsedDefaultArg()) if (PVD->hasDefaultArg() && !PVD->hasUnparsedDefaultArg())
@ -3008,8 +3034,11 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
} }
else else
F->qualifiedType = GetQualifiedType(FD->getType()); 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); const auto& Mangled = GetDeclMangledName(FD);
F->mangled = Mangled; F->mangled = Mangled;
@ -3047,7 +3076,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
if (GetDeclText(Range, Sig)) if (GetDeclText(Range, Sig))
F->signature = Sig; F->signature = Sig;
for (const auto& VD : FD->parameters()) for (auto VD : FD->parameters())
{ {
auto P = WalkParameter(VD, ParamStartLoc); auto P = WalkParameter(VD, ParamStartLoc);
F->Parameters.push_back(P); F->Parameters.push_back(P);
@ -3069,6 +3098,9 @@ 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);
if (F->isDependent)
return;
const CXXMethodDecl* MD; const CXXMethodDecl* MD;
if ((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() && if ((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() &&
!HasLayout(cast<CXXRecordDecl>(MD->getDeclContext()))) !HasLayout(cast<CXXRecordDecl>(MD->getDeclContext())))
@ -3874,39 +3906,6 @@ Declaration* Parser::WalkDeclaration(const clang::Decl* D)
return Decl; 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) void Parser::HandleDiagnostics(ParserResult* res)
{ {
auto DiagClient = (DiagnosticConsumer&) c->getDiagnosticClient(); auto DiagClient = (DiagnosticConsumer&) c->getDiagnosticClient();

2
src/CppParser/Parser.h

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

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

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

Loading…
Cancel
Save