Skip to content

Commit

Permalink
Revert two patches to fix GH58452 regression
Browse files Browse the repository at this point in the history
GH58452 is a regression in the 16.0 release branch caused by both:
b8a1b69 and
3a0309c

This patch reverts both of those to make the 'valid' code stop
diagnosing
at the expense of crashes on invalid + unclear diagnostics.

This patch also adds the tests from GH58452 to prevent any
re-application from breaking this again.

Revert "[clang] Improve diagnostics for expansion length mismatch"
This reverts commit 3a0309c.
Revert "[clang] fix missing initialization of original number of expansions"
This reverts commit b8a1b69.

Differential Revision: https://reviews.llvm.org/D145605

(cherry picked from commit acecf68)
  • Loading branch information
Erich Keane authored and tstellar committed Mar 10, 2023
1 parent 633c6c0 commit 9a6f0c2
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 176 deletions.
8 changes: 3 additions & 5 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,9 @@ namespace threadSafety {

// FIXME: No way to easily map from TemplateTypeParmTypes to
// TemplateTypeParmDecls, so we have this horrible PointerUnion.
using UnexpandedParameterPack = std::pair<
llvm::PointerUnion<
const TemplateTypeParmType *, const SubstTemplateTypeParmPackType *,
const SubstNonTypeTemplateParmPackExpr *, const NamedDecl *>,
SourceLocation>;
typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *>,
SourceLocation>
UnexpandedParameterPack;

/// Describes whether we've seen any nullability information for the given
/// file.
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Sema/SemaInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ inline InheritableAttr *getDLLAttr(Decl *D) {
}

/// Retrieve the depth and index of a template parameter.
inline std::pair<unsigned, unsigned> getDepthAndIndex(const NamedDecl *ND) {
inline std::pair<unsigned, unsigned> getDepthAndIndex(NamedDecl *ND) {
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
return std::make_pair(TTP->getDepth(), TTP->getIndex());

Expand All @@ -79,7 +79,7 @@ getDepthAndIndex(UnexpandedParameterPack UPP) {
if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>())
return std::make_pair(TTP->getDepth(), TTP->getIndex());

return getDepthAndIndex(UPP.first.get<const NamedDecl *>());
return getDepthAndIndex(UPP.first.get<NamedDecl *>());
}

class TypoCorrectionConsumer : public VisibleDeclConsumer {
Expand Down
7 changes: 2 additions & 5 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,11 +756,8 @@ class PackDeductionScope {
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
UnexpandedParameterPack U = Unexpanded[I];
if (U.first.is<const SubstTemplateTypeParmPackType *>() ||
U.first.is<const SubstNonTypeTemplateParmPackExpr *>())
continue;
auto [Depth, Index] = getDepthAndIndex(U);
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == Info.getDeducedDepth())
AddPack(Index);
}
Expand Down
234 changes: 114 additions & 120 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,6 @@ namespace {
return true;
}

bool
VisitSubstTemplateTypeParmPackTypeLoc(SubstTemplateTypeParmPackTypeLoc TL) {
Unexpanded.push_back({TL.getTypePtr(), TL.getNameLoc()});
return true;
}

bool VisitSubstTemplateTypeParmPackType(SubstTemplateTypeParmPackType *T) {
Unexpanded.push_back({T, SourceLocation()});
return true;
}

bool
VisitSubstNonTypeTemplateParmPackExpr(SubstNonTypeTemplateParmPackExpr *E) {
Unexpanded.push_back({E, E->getParameterPackLocation()});
return true;
}

/// Record occurrences of function and non-type template
/// parameter packs in an expression.
bool VisitDeclRefExpr(DeclRefExpr *E) {
Expand Down Expand Up @@ -324,8 +307,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
auto *TTPD = dyn_cast<TemplateTypeParmDecl>(LocalPack);
return TTPD && TTPD->getTypeForDecl() == TTPT;
}
return declaresSameEntity(Pack.first.get<const NamedDecl *>(),
LocalPack);
return declaresSameEntity(Pack.first.get<NamedDecl *>(), LocalPack);
};
if (llvm::any_of(LSI->LocalPacks, DeclaresThisPack))
LambdaParamPackReferences.push_back(Pack);
Expand Down Expand Up @@ -377,7 +359,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
Name = TTP->getIdentifier();
else
Name = Unexpanded[I].first.get<const NamedDecl *>()->getIdentifier();
Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();

if (Name && NamesKnown.insert(Name).second)
Names.push_back(Name);
Expand Down Expand Up @@ -440,7 +422,7 @@ bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) {
llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end());
SmallVector<UnexpandedParameterPack, 2> UnexpandedParms;
for (auto Parm : Unexpanded)
if (ParmSet.contains(Parm.first.dyn_cast<const NamedDecl *>()))
if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl *>()))
UnexpandedParms.push_back(Parm);
if (UnexpandedParms.empty())
return false;
Expand Down Expand Up @@ -692,95 +674,109 @@ bool Sema::CheckParameterPacksForExpansion(
bool &RetainExpansion, std::optional<unsigned> &NumExpansions) {
ShouldExpand = true;
RetainExpansion = false;
std::pair<const IdentifierInfo *, SourceLocation> FirstPack;
std::optional<std::pair<unsigned, SourceLocation>> PartialExpansion;
std::optional<unsigned> CurNumExpansions;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;
std::optional<unsigned> NumPartialExpansions;
SourceLocation PartiallySubstitutedPackLoc;

for (auto [P, Loc] : Unexpanded) {
for (UnexpandedParameterPack ParmPack : Unexpanded) {
// Compute the depth and index for this parameter pack.
std::optional<std::pair<unsigned, unsigned>> Pos;
unsigned Depth = 0, Index = 0;
IdentifierInfo *Name;
bool IsVarDeclPack = false;

if (const TemplateTypeParmType *TTP =
ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth();
Index = TTP->getIndex();
Name = TTP->getIdentifier();
} else {
NamedDecl *ND = ParmPack.first.get<NamedDecl *>();
if (isa<VarDecl>(ND))
IsVarDeclPack = true;
else
std::tie(Depth, Index) = getDepthAndIndex(ND);

Name = ND->getIdentifier();
}

// Determine the size of this argument pack.
unsigned NewPackSize;
const auto *ND = P.dyn_cast<const NamedDecl *>();
if (ND && isa<VarDecl>(ND)) {
const auto *DAP =
CurrentInstantiationScope->findInstantiationOf(ND)
->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>();
if (!DAP) {
if (IsVarDeclPack) {
// Figure out whether we're instantiating to an argument pack or not.
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;

llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
CurrentInstantiationScope->findInstantiationOf(
ParmPack.first.get<NamedDecl *>());
if (Instantiation->is<DeclArgumentPack *>()) {
// We could expand this function parameter pack.
NewPackSize = Instantiation->get<DeclArgumentPack *>()->size();
} else {
// We can't expand this function parameter pack, so we can't expand
// the pack expansion.
ShouldExpand = false;
continue;
}
NewPackSize = DAP->size();
} else if (ND) {
Pos = getDepthAndIndex(ND);
} else if (const auto *TTP = P.dyn_cast<const TemplateTypeParmType *>()) {
Pos = {TTP->getDepth(), TTP->getIndex()};
ND = TTP->getDecl();
// FIXME: We either should have some fallback for canonical TTP, or
// never have canonical TTP here.
} else if (const auto *STP =
P.dyn_cast<const SubstTemplateTypeParmPackType *>()) {
NewPackSize = STP->getNumArgs();
ND = STP->getReplacedParameter();
} else {
const auto *SEP = P.get<const SubstNonTypeTemplateParmPackExpr *>();
NewPackSize = SEP->getArgumentPack().pack_size();
ND = SEP->getParameterPack();
}

if (Pos) {
// If we don't have a template argument at this depth/index, then we
// cannot expand the pack expansion. Make a note of this, but we still
// want to check any parameter packs we *do* have arguments for.
if (Pos->first >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Pos->first, Pos->second)) {
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index)) {
ShouldExpand = false;
continue;
}

// Determine the size of the argument pack.
NewPackSize = TemplateArgs(Pos->first, Pos->second).pack_size();
// C++0x [temp.arg.explicit]p9:
// Template argument deduction can extend the sequence of template
// arguments corresponding to a template parameter pack, even when the
// sequence contains explicitly specified template arguments.
if (CurrentInstantiationScope)
if (const NamedDecl *PartialPack =
CurrentInstantiationScope->getPartiallySubstitutedPack();
PartialPack && getDepthAndIndex(PartialPack) == *Pos) {
NewPackSize = TemplateArgs(Depth, Index).pack_size();
}

// C++0x [temp.arg.explicit]p9:
// Template argument deduction can extend the sequence of template
// arguments corresponding to a template parameter pack, even when the
// sequence contains explicitly specified template arguments.
if (!IsVarDeclPack && CurrentInstantiationScope) {
if (NamedDecl *PartialPack =
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
unsigned PartialDepth, PartialIndex;
std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
if (PartialDepth == Depth && PartialIndex == Index) {
RetainExpansion = true;
// We don't actually know the new pack size yet.
PartialExpansion = {NewPackSize, Loc};
NumPartialExpansions = NewPackSize;
PartiallySubstitutedPackLoc = ParmPack.second;
continue;
}
}
}

// FIXME: Workaround for Canonical TTP.
const IdentifierInfo *Name = ND ? ND->getIdentifier() : nullptr;
if (!CurNumExpansions) {
if (!NumExpansions) {
// The is the first pack we've seen for which we have an argument.
// Record it.
CurNumExpansions = NewPackSize;
FirstPack = {Name, Loc};
} else if (NewPackSize != *CurNumExpansions) {
NumExpansions = NewPackSize;
FirstPack.first = Name;
FirstPack.second = ParmPack.second;
HaveFirstPack = true;
continue;
}

if (NewPackSize != *NumExpansions) {
// C++0x [temp.variadic]p5:
// All of the parameter packs expanded by a pack expansion shall have
// the same number of arguments specified.
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
<< FirstPack.first << Name << *CurNumExpansions << NewPackSize
<< SourceRange(FirstPack.second) << SourceRange(Loc);
if (HaveFirstPack)
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
<< FirstPack.first << Name << *NumExpansions << NewPackSize
<< SourceRange(FirstPack.second) << SourceRange(ParmPack.second);
else
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
<< Name << *NumExpansions << NewPackSize
<< SourceRange(ParmPack.second);
return true;
}
}

if (NumExpansions && CurNumExpansions &&
*NumExpansions != *CurNumExpansions) {
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
<< FirstPack.first << *CurNumExpansions << *NumExpansions
<< SourceRange(FirstPack.second);
return true;
}

// If we're performing a partial expansion but we also have a full expansion,
// expand to the number of common arguments. For example, given:
//
Expand All @@ -790,18 +786,17 @@ bool Sema::CheckParameterPacksForExpansion(
//
// ... a call to 'A<int, int>().f<int>' should expand the pack once and
// retain an expansion.
if (PartialExpansion) {
if (CurNumExpansions && *CurNumExpansions < PartialExpansion->first) {
if (NumPartialExpansions) {
if (NumExpansions && *NumExpansions < *NumPartialExpansions) {
NamedDecl *PartialPack =
CurrentInstantiationScope->getPartiallySubstitutedPack();
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial)
<< PartialPack << PartialExpansion->first << *CurNumExpansions
<< SourceRange(PartialExpansion->second);
<< PartialPack << *NumPartialExpansions << *NumExpansions
<< SourceRange(PartiallySubstitutedPackLoc);
return true;
}
NumExpansions = PartialExpansion->first;
} else {
NumExpansions = CurNumExpansions;

NumExpansions = NumPartialExpansions;
}

return false;
Expand All @@ -814,48 +809,47 @@ std::optional<unsigned> Sema::getNumArgumentsInExpansion(
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);

std::optional<unsigned> Result;
auto setResultSz = [&Result](unsigned Size) {
assert((!Result || *Result == Size) && "inconsistent pack sizes");
Result = Size;
};
auto setResultPos = [&](const std::pair<unsigned, unsigned> &Pos) -> bool {
unsigned Depth = Pos.first, Index = Pos.second;
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index))
// The pattern refers to an unknown template argument. We're not ready to
// expand this pack yet.
return true;
// Determine the size of the argument pack.
setResultSz(TemplateArgs(Depth, Index).pack_size());
return false;
};
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
// Compute the depth and index for this parameter pack.
unsigned Depth;
unsigned Index;

for (auto [I, _] : Unexpanded) {
if (const auto *TTP = I.dyn_cast<const TemplateTypeParmType *>()) {
if (setResultPos({TTP->getDepth(), TTP->getIndex()}))
return std::nullopt;
} else if (const auto *STP =
I.dyn_cast<const SubstTemplateTypeParmPackType *>()) {
setResultSz(STP->getNumArgs());
} else if (const auto *SEP =
I.dyn_cast<const SubstNonTypeTemplateParmPackExpr *>()) {
setResultSz(SEP->getArgumentPack().pack_size());
if (const TemplateTypeParmType *TTP =
Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth();
Index = TTP->getIndex();
} else {
const auto *ND = I.get<const NamedDecl *>();
// Function parameter pack or init-capture pack.
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
if (isa<VarDecl>(ND)) {
const auto *DAP =
CurrentInstantiationScope->findInstantiationOf(ND)
->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>();
if (!DAP)
// Function parameter pack or init-capture pack.
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;

llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
CurrentInstantiationScope->findInstantiationOf(
Unexpanded[I].first.get<NamedDecl *>());
if (Instantiation->is<Decl *>())
// The pattern refers to an unexpanded pack. We're not ready to expand
// this pack yet.
return std::nullopt;
setResultSz(DAP->size());
} else if (setResultPos(getDepthAndIndex(ND))) {
return std::nullopt;

unsigned Size = Instantiation->get<DeclArgumentPack *>()->size();
assert((!Result || *Result == Size) && "inconsistent pack sizes");
Result = Size;
continue;
}

std::tie(Depth, Index) = getDepthAndIndex(ND);
}
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index))
// The pattern refers to an unknown template argument. We're not ready to
// expand this pack yet.
return std::nullopt;

// Determine the size of the argument pack.
unsigned Size = TemplateArgs(Depth, Index).pack_size();
assert((!Result || *Result == Size) && "inconsistent pack sizes");
Result = Size;
}

return Result;
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -5897,7 +5897,6 @@ bool TreeTransform<Derived>::TransformFunctionTypeParams(
= dyn_cast<PackExpansionType>(OldType)) {
// We have a function parameter pack that may need to be expanded.
QualType Pattern = Expansion->getPattern();
NumExpansions = Expansion->getNumExpansions();
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);

Expand Down

0 comments on commit 9a6f0c2

Please sign in to comment.