Skip to content

Commit a69f6d1

Browse files
committed
Generate valid C++ for specialisations with void
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent dddd5da commit a69f6d1

File tree

5 files changed

+56
-24
lines changed

5 files changed

+56
-24
lines changed

src/CppParser/Parser.cpp

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,18 +2978,19 @@ static const clang::CodeGen::CGFunctionInfo& GetCodeGenFunctionInfo(
29782978
FTy.castAs<clang::FunctionProtoType>());
29792979
}
29802980

2981-
bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
2981+
bool Parser::CanCheckCodeGenInfo(const clang::Type* Ty)
29822982
{
29832983
auto FinalType = GetFinalType(Ty);
29842984

29852985
if (FinalType->isDependentType() ||
2986-
FinalType->isInstantiationDependentType() || FinalType->isUndeducedType())
2986+
FinalType->isInstantiationDependentType() ||
2987+
FinalType->isUndeducedType())
29872988
return false;
29882989

29892990
if (FinalType->isFunctionType())
29902991
{
29912992
auto FTy = FinalType->getAs<clang::FunctionType>();
2992-
auto CanCheck = CanCheckCodeGenInfo(S, FTy->getReturnType().getTypePtr());
2993+
auto CanCheck = CanCheckCodeGenInfo(FTy->getReturnType().getTypePtr());
29932994
if (!CanCheck)
29942995
return false;
29952996

@@ -2998,7 +2999,7 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
29982999
auto FPTy = FinalType->getAs<clang::FunctionProtoType>();
29993000
for (const auto& ParamType : FPTy->getParamTypes())
30003001
{
3001-
auto CanCheck = CanCheckCodeGenInfo(S, ParamType.getTypePtr());
3002+
auto CanCheck = CanCheckCodeGenInfo(ParamType.getTypePtr());
30023003
if (!CanCheck)
30033004
return false;
30043005
}
@@ -3015,7 +3016,8 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
30153016
{
30163017
if (auto MPT = Ty->getAs<clang::MemberPointerType>())
30173018
if (!MPT->isDependentType())
3018-
S.RequireCompleteType(clang::SourceLocation(), clang::QualType(Ty, 0), 1);
3019+
c->getSema().RequireCompleteType(clang::SourceLocation(),
3020+
clang::QualType(Ty, 0), 1);
30193021
}
30203022

30213023
return true;
@@ -3088,7 +3090,7 @@ void Parser::InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* C
30883090
if (!CTS->isCompleteDefinition())
30893091
{
30903092
c->getSema().InstantiateClassTemplateSpecialization(CTS->getBeginLoc(),
3091-
CTS, TSK_ImplicitInstantiation, false);
3093+
CTS, clang::TemplateSpecializationKind::TSK_ImplicitInstantiation, false);
30923094
}
30933095

30943096
for (auto Decl : CTS->decls())
@@ -3101,7 +3103,7 @@ void Parser::InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* C
31013103
{
31023104
c->getSema().InstantiateClass(Nested->getBeginLoc(), Nested, Template,
31033105
MultiLevelTemplateArgumentList(CTS->getTemplateArgs()),
3104-
TSK_ImplicitInstantiation, false);
3106+
clang::TemplateSpecializationKind::TSK_ImplicitInstantiation, false);
31053107
}
31063108
}
31073109
}
@@ -3210,7 +3212,8 @@ void Parser::MarkValidity(Function* F)
32103212

32113213
auto FD = static_cast<FunctionDecl*>(F->originalPtr);
32123214

3213-
if (!FD->getTemplateInstantiationPattern() || !FD->isExternallyVisible())
3215+
if (!FD->isImplicit() &&
3216+
(!FD->getTemplateInstantiationPattern() || !FD->isExternallyVisible()))
32143217
return;
32153218

32163219
auto existingClient = c->getSema().getDiagnostics().getClient();
@@ -3230,6 +3233,18 @@ void Parser::MarkValidity(Function* F)
32303233
F->isInvalid = IsInvalid(FD->getBody(), Bodies);
32313234
}
32323235

3236+
if (!F->isInvalid)
3237+
{
3238+
DeclContext* Context = FD->getDeclContext();
3239+
while (Context)
3240+
{
3241+
F->isInvalid = cast<Decl>(Context)->isInvalidDecl();
3242+
if (F->isInvalid)
3243+
break;
3244+
Context = Context->getParent();
3245+
}
3246+
}
3247+
32333248
c->getSema().getDiagnostics().setClient(existingClient, false);
32343249
c->getSema().TUScope = nullptr;
32353250
}
@@ -3332,13 +3347,10 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
33323347
ParamStartLoc = VD->getEndLoc();
33333348
}
33343349

3335-
if (!opts->skipFunctionBodies)
3350+
if (!opts->skipFunctionBodies && FD->hasBody())
33363351
{
3337-
if (FD->hasBody())
3338-
{
3339-
if (auto Body = FD->getBody())
3340-
F->bodyStmt = WalkStatement(Body);
3341-
}
3352+
if (auto Body = FD->getBody())
3353+
F->bodyStmt = WalkStatement(Body);
33423354
}
33433355

33443356
auto& CXXABI = codeGenTypes->getCXXABI();
@@ -3355,15 +3367,17 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
33553367
if (auto FTSI = FD->getTemplateSpecializationInfo())
33563368
F->specializationInfo = WalkFunctionTemplateSpec(FTSI, F);
33573369

3370+
MarkValidity(F);
3371+
F->qualifiedType = GetQualifiedType(FD->getType(), &FTL);
3372+
33583373
const CXXMethodDecl* MD;
33593374
if (FD->isDependentContext() ||
33603375
((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() &&
33613376
!HasLayout(cast<CXXRecordDecl>(MD->getDeclContext()))) ||
3362-
!CanCheckCodeGenInfo(c->getSema(), FD->getReturnType().getTypePtr()) ||
3377+
!CanCheckCodeGenInfo(FD->getReturnType().getTypePtr()) ||
33633378
std::any_of(FD->parameters().begin(), FD->parameters().end(),
3364-
[this](auto* P) { return !CanCheckCodeGenInfo(c->getSema(), P->getType().getTypePtr()); }))
3379+
[this](auto* P) { return !CanCheckCodeGenInfo(P->getType().getTypePtr()); }))
33653380
{
3366-
F->qualifiedType = GetQualifiedType(FD->getType(), &FTL);
33673381
return;
33683382
}
33693383

@@ -3377,9 +3391,6 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
33773391
F->Parameters[Index++]->isIndirect =
33783392
Arg.info.isIndirect() && !Arg.info.getIndirectByVal();
33793393
}
3380-
3381-
MarkValidity(F);
3382-
F->qualifiedType = GetQualifiedType(FD->getType(), &FTL);
33833394
}
33843395

33853396
Function* Parser::WalkFunction(const clang::FunctionDecl* FD)

src/CppParser/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class Parser
135135
bool IsValidDeclaration(const clang::SourceLocation& Loc);
136136
std::string GetDeclMangledName(const clang::Decl* D);
137137
std::string GetTypeName(const clang::Type* Type);
138-
bool CanCheckCodeGenInfo(clang::Sema & S, const clang::Type * Ty);
138+
bool CanCheckCodeGenInfo(const clang::Type* Ty);
139139
void CompleteIfSpecializationType(const clang::QualType& QualType);
140140
void InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* CTS);
141141
Parameter* WalkParameter(const clang::ParmVarDecl* PVD,

src/Generator/Generators/CSharp/CSharpSources.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,10 @@ private IEnumerable<Class> GetGeneratedClasses(
365365
if (dependentClass.HasDependentValueFieldInLayout())
366366
return specializedClasses.KeepSingleAllPointersSpecialization();
367367

368-
return new[] { specializedClasses.FirstOrDefault(s => s.IsGenerated) ??
368+
return new[] {
369+
specializedClasses.FirstOrDefault(
370+
s => s.IsGenerated && s.Classes.All(c => !c.IsIncomplete)) ??
371+
specializedClasses.FirstOrDefault(s => s.IsGenerated) ??
369372
specializedClasses.First()};
370373
}
371374

tests/CSharp/CSharpTemplates.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool>
120120
{
121121
}
122122

123-
void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii)
123+
void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii, Base<void> _24)
124124
{
125125
}
126126

tests/CSharp/CSharpTemplates.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,27 @@ template <typename T>
195195
class Base
196196
{
197197
public:
198+
class Nested
199+
{
200+
public:
201+
void f(const T& t);
202+
friend void f(Nested& n) {}
203+
};
204+
void invokeFriend();
198205
typedef T* typedefT;
199206
};
200207

208+
template <typename T>
209+
void Base<T>::Nested::f(const T& t)
210+
{
211+
}
212+
213+
template <typename T>
214+
void Base<T>::invokeFriend()
215+
{
216+
f(Nested());
217+
}
218+
201219
template <typename T>
202220
class DependentValueFields : public Base<T>
203221
{
@@ -844,7 +862,7 @@ void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool>
844862
VirtualDependentValueFields<float> _22, VirtualDependentValueFields<const char*> _23,
845863
std::string s);
846864

847-
void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii);
865+
void hasIgnoredParam(DependentValueFields<IndependentFields<Ignored>> ii, Base<void> _24);
848866

849867
std::map<int, int> usesValidSpecialisationOfIgnoredTemplate();
850868

0 commit comments

Comments
 (0)