mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 08:06:40 +00:00
This reverts commit 4336f00f2156970cc0af2816331387a0a4039317.
This commit is contained in:
parent
ac3321f104
commit
91dd4ec20e
@ -468,7 +468,6 @@ Bug Fixes to C++ Support
|
||||
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
|
||||
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
|
||||
- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
|
||||
- Clang is now better at keeping track of friend function template instance contexts. (#GH55509)
|
||||
- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
|
||||
- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
|
||||
containing outer unexpanded parameters were not correctly expanded. (#GH101754)
|
||||
|
@ -2299,13 +2299,6 @@ public:
|
||||
FunctionDeclBits.IsLateTemplateParsed = ILT;
|
||||
}
|
||||
|
||||
bool isInstantiatedFromMemberTemplate() const {
|
||||
return FunctionDeclBits.IsInstantiatedFromMemberTemplate;
|
||||
}
|
||||
void setInstantiatedFromMemberTemplate(bool Val = true) {
|
||||
FunctionDeclBits.IsInstantiatedFromMemberTemplate = Val;
|
||||
}
|
||||
|
||||
/// Whether this function is "trivial" in some specialized C++ senses.
|
||||
/// Can only be true for default constructors, copy constructors,
|
||||
/// copy assignment operators, and destructors. Not meaningful until
|
||||
|
@ -1763,8 +1763,6 @@ class DeclContext {
|
||||
uint64_t HasImplicitReturnZero : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint64_t IsLateTemplateParsed : 1;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint64_t IsInstantiatedFromMemberTemplate : 1;
|
||||
|
||||
/// Kind of contexpr specifier as defined by ConstexprSpecKind.
|
||||
LLVM_PREFERRED_TYPE(ConstexprSpecKind)
|
||||
@ -1815,7 +1813,7 @@ class DeclContext {
|
||||
};
|
||||
|
||||
/// Number of inherited and non-inherited bits in FunctionDeclBitfields.
|
||||
enum { NumFunctionDeclBits = NumDeclContextBits + 32 };
|
||||
enum { NumFunctionDeclBits = NumDeclContextBits + 31 };
|
||||
|
||||
/// Stores the bits used by CXXConstructorDecl. If modified
|
||||
/// NumCXXConstructorDeclBits and the accessor
|
||||
@ -1826,12 +1824,12 @@ class DeclContext {
|
||||
LLVM_PREFERRED_TYPE(FunctionDeclBitfields)
|
||||
uint64_t : NumFunctionDeclBits;
|
||||
|
||||
/// 19 bits to fit in the remaining available space.
|
||||
/// 20 bits to fit in the remaining available space.
|
||||
/// Note that this makes CXXConstructorDeclBitfields take
|
||||
/// exactly 64 bits and thus the width of NumCtorInitializers
|
||||
/// will need to be shrunk if some bit is added to NumDeclContextBitfields,
|
||||
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
|
||||
uint64_t NumCtorInitializers : 16;
|
||||
uint64_t NumCtorInitializers : 17;
|
||||
LLVM_PREFERRED_TYPE(bool)
|
||||
uint64_t IsInheritingConstructor : 1;
|
||||
|
||||
@ -1845,7 +1843,7 @@ class DeclContext {
|
||||
};
|
||||
|
||||
/// Number of inherited and non-inherited bits in CXXConstructorDeclBitfields.
|
||||
enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 19 };
|
||||
enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 20 };
|
||||
|
||||
/// Stores the bits used by ObjCMethodDecl.
|
||||
/// If modified NumObjCMethodDeclBits and the accessor
|
||||
|
@ -1008,15 +1008,6 @@ public:
|
||||
return getTemplatedDecl()->isThisDeclarationADefinition();
|
||||
}
|
||||
|
||||
bool isCompatibleWithDefinition() const {
|
||||
return getTemplatedDecl()->isInstantiatedFromMemberTemplate() ||
|
||||
isThisDeclarationADefinition();
|
||||
}
|
||||
void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *D) {
|
||||
getTemplatedDecl()->setInstantiatedFromMemberTemplate();
|
||||
RedeclarableTemplateDecl::setInstantiatedFromMemberTemplate(D);
|
||||
}
|
||||
|
||||
/// Return the specialization with the provided arguments if it exists,
|
||||
/// otherwise return the insertion point.
|
||||
FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args,
|
||||
|
@ -13017,12 +13017,6 @@ public:
|
||||
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
|
||||
bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);
|
||||
|
||||
void getTemplateInstantiationArgs(
|
||||
MultiLevelTemplateArgumentList &Result, const NamedDecl *D,
|
||||
const DeclContext *DC = nullptr, bool Final = false,
|
||||
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
|
||||
bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);
|
||||
|
||||
/// RAII object to handle the state changes required to synthesize
|
||||
/// a function body.
|
||||
class SynthesizedFunctionScope {
|
||||
|
@ -3067,7 +3067,6 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
||||
FunctionDeclBits.IsIneligibleOrNotSelected = false;
|
||||
FunctionDeclBits.HasImplicitReturnZero = false;
|
||||
FunctionDeclBits.IsLateTemplateParsed = false;
|
||||
FunctionDeclBits.IsInstantiatedFromMemberTemplate = false;
|
||||
FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind);
|
||||
FunctionDeclBits.BodyContainsImmediateEscalatingExpression = false;
|
||||
FunctionDeclBits.InstantiationIsPending = false;
|
||||
|
@ -3928,7 +3928,22 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
|
||||
if (FunctionTemplate->getFriendObjectKind())
|
||||
Owner = FunctionTemplate->getLexicalDeclContext();
|
||||
FunctionDecl *FD = FunctionTemplate->getTemplatedDecl();
|
||||
|
||||
// additional check for inline friend,
|
||||
// ```
|
||||
// template <class F1> int foo(F1 X);
|
||||
// template <int A1> struct A {
|
||||
// template <class F1> friend int foo(F1 X) { return A1; }
|
||||
// };
|
||||
// template struct A<1>;
|
||||
// int a = foo(1.0);
|
||||
// ```
|
||||
const FunctionDecl *FDFriend;
|
||||
if (FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None &&
|
||||
FD->isDefined(FDFriend, /*CheckForPendingFriendDefinition*/ true) &&
|
||||
FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) {
|
||||
FD = const_cast<FunctionDecl *>(FDFriend);
|
||||
Owner = FD->getLexicalDeclContext();
|
||||
}
|
||||
MultiLevelTemplateArgumentList SubstArgs(
|
||||
FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
|
||||
/*Final=*/false);
|
||||
|
@ -512,13 +512,13 @@ struct TemplateInstantiationArgumentCollecter
|
||||
|
||||
} // namespace
|
||||
|
||||
void Sema::getTemplateInstantiationArgs(
|
||||
MultiLevelTemplateArgumentList &Result, const NamedDecl *ND,
|
||||
const DeclContext *DC, bool Final,
|
||||
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
|
||||
const NamedDecl *ND, const DeclContext *DC, bool Final,
|
||||
std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
|
||||
bool ForConstraintInstantiation) {
|
||||
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
|
||||
// Accumulate the set of template argument lists in this structure.
|
||||
MultiLevelTemplateArgumentList Result;
|
||||
const Decl *CurDecl = ND;
|
||||
|
||||
if (!CurDecl)
|
||||
@ -529,17 +529,6 @@ void Sema::getTemplateInstantiationArgs(
|
||||
do {
|
||||
CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
|
||||
} while (CurDecl);
|
||||
}
|
||||
|
||||
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
|
||||
const NamedDecl *ND, const DeclContext *DC, bool Final,
|
||||
std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
|
||||
bool ForConstraintInstantiation) {
|
||||
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
|
||||
// Accumulate the set of template argument lists in this structure.
|
||||
MultiLevelTemplateArgumentList Result;
|
||||
getTemplateInstantiationArgs(Result, ND, DC, Final, Innermost,
|
||||
RelativeToPrimary, ForConstraintInstantiation);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -5224,26 +5224,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
RebuildTypeSourceInfoForDefaultSpecialMembers();
|
||||
SetDeclDefaulted(Function, PatternDecl->getLocation());
|
||||
} else {
|
||||
DeclContext *DC = Function;
|
||||
MultiLevelTemplateArgumentList TemplateArgs;
|
||||
if (auto *Primary = Function->getPrimaryTemplate();
|
||||
Primary &&
|
||||
!isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) {
|
||||
auto It = llvm::find_if(Primary->redecls(),
|
||||
[](const RedeclarableTemplateDecl *RTD) {
|
||||
return cast<FunctionTemplateDecl>(RTD)
|
||||
->isCompatibleWithDefinition();
|
||||
});
|
||||
assert(It != Primary->redecls().end() &&
|
||||
"Should't get here without a definition");
|
||||
DC = (*It)->getLexicalDeclContext();
|
||||
if (Function->getTemplateSpecializationKind() !=
|
||||
TSK_ExplicitSpecialization)
|
||||
TemplateArgs.addOuterTemplateArguments(
|
||||
Function, Function->getTemplateSpecializationArgs()->asArray(),
|
||||
/*Final=*/false);
|
||||
}
|
||||
getTemplateInstantiationArgs(TemplateArgs, /*D=*/nullptr, DC);
|
||||
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
|
||||
Function, Function->getLexicalDeclContext());
|
||||
|
||||
// Substitute into the qualifier; we can get a substitution failure here
|
||||
// through evil use of alias templates.
|
||||
|
@ -1087,7 +1087,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
||||
FD->setHasImplicitReturnZero(FunctionDeclBits.getNextBit());
|
||||
FD->setIsMultiVersion(FunctionDeclBits.getNextBit());
|
||||
FD->setLateTemplateParsed(FunctionDeclBits.getNextBit());
|
||||
FD->setInstantiatedFromMemberTemplate(FunctionDeclBits.getNextBit());
|
||||
FD->setFriendConstraintRefersToEnclosingTemplate(
|
||||
FunctionDeclBits.getNextBit());
|
||||
FD->setUsesSEHTry(FunctionDeclBits.getNextBit());
|
||||
|
@ -626,7 +626,7 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
static_assert(DeclContext::NumFunctionDeclBits == 45,
|
||||
static_assert(DeclContext::NumFunctionDeclBits == 44,
|
||||
"You need to update the serializer after you change the "
|
||||
"FunctionDeclBits");
|
||||
|
||||
@ -732,7 +732,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
FunctionDeclBits.addBit(D->hasImplicitReturnZero());
|
||||
FunctionDeclBits.addBit(D->isMultiVersion());
|
||||
FunctionDeclBits.addBit(D->isLateTemplateParsed());
|
||||
FunctionDeclBits.addBit(D->isInstantiatedFromMemberTemplate());
|
||||
FunctionDeclBits.addBit(D->FriendConstraintRefersToEnclosingTemplate());
|
||||
FunctionDeclBits.addBit(D->usesSEHTry());
|
||||
Record.push_back(FunctionDeclBits);
|
||||
|
@ -1,101 +0,0 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++26 %s
|
||||
|
||||
namespace t1 {
|
||||
template<int N> struct A {
|
||||
template<class C> friend auto cica(const A<N-1>&, C) {
|
||||
return N;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct A<0> {
|
||||
template<class C> friend auto cica(const A<0>&, C);
|
||||
// expected-note@-1 {{declared here}}
|
||||
};
|
||||
|
||||
void test() {
|
||||
cica(A<0>{}, 0);
|
||||
// expected-error@-1 {{function 'cica<int>' with deduced return type cannot be used before it is defined}}
|
||||
|
||||
(void)A<1>{};
|
||||
cica(A<0>{}, 0);
|
||||
}
|
||||
} // namespace t1
|
||||
namespace t2 {
|
||||
template<int N> struct A {
|
||||
template<class C> friend auto cica(const A<N-1>&, C) {
|
||||
return N;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct A<0> {
|
||||
template<class C> friend auto cica(const A<0>&, C);
|
||||
};
|
||||
|
||||
template <int N, class = decltype(cica(A<N>{}, nullptr))>
|
||||
void MakeCica();
|
||||
// expected-note@-1 {{candidate function}}
|
||||
|
||||
template <int N> void MakeCica(A<N+1> = {});
|
||||
// expected-note@-1 {{candidate function}}
|
||||
|
||||
void test() {
|
||||
MakeCica<0>();
|
||||
|
||||
MakeCica<0>();
|
||||
// expected-error@-1 {{call to 'MakeCica' is ambiguous}}
|
||||
}
|
||||
} // namespace t2
|
||||
namespace t3 {
|
||||
template<int N> struct A {
|
||||
template<class C> friend auto cica(const A<N-1>&, C) {
|
||||
return N-1;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct A<0> {
|
||||
template<class C> friend auto cica(const A<0>&, C);
|
||||
};
|
||||
|
||||
template <int N, class AT, class = decltype(cica(AT{}, nullptr))>
|
||||
static constexpr bool MakeCica(int);
|
||||
|
||||
template <int N, class AT>
|
||||
static constexpr bool MakeCica(short, A<N+1> = {});
|
||||
|
||||
template <int N, class AT = A<N>, class Val = decltype(MakeCica<N, AT>(0))>
|
||||
static constexpr bool has_cica = Val{};
|
||||
|
||||
constexpr bool cica2 = has_cica<0> || has_cica<0>;
|
||||
} // namespace t3
|
||||
namespace t4 {
|
||||
template<int N> struct A {
|
||||
template<class C> friend auto cica(const A<N-1>&, C);
|
||||
};
|
||||
|
||||
template<> struct A<0> {
|
||||
template<class C> friend auto cica(const A<0>&, C) {
|
||||
C a;
|
||||
}
|
||||
};
|
||||
|
||||
template struct A<1>;
|
||||
|
||||
void test() {
|
||||
cica(A<0>{}, 0);
|
||||
}
|
||||
} // namespace t4
|
||||
namespace regression1 {
|
||||
template <class> class A;
|
||||
|
||||
template <class T> [[gnu::abi_tag("TAG")]] void foo(A<T>);
|
||||
|
||||
template <class> struct A {
|
||||
friend void foo <>(A);
|
||||
};
|
||||
|
||||
template struct A<int>;
|
||||
|
||||
template <class T> [[gnu::abi_tag("TAG")]] void foo(A<T>) {}
|
||||
|
||||
template void foo<int>(A<int>);
|
||||
} // namespace regression1
|
Loading…
x
Reference in New Issue
Block a user