[Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (#100392)
A class member named by an expression in a member function that may instantiate to a static _or_ non-static member is represented by a `UnresolvedLookupExpr` in order to defer the implicit transformation to a class member access expression until instantiation. Since `ASTContext::getDecltypeType` only creates a `DecltypeType` that has a `DependentDecltypeType` as its canonical type when the operand is instantiation dependent, and since we do not transform types unless they are instantiation dependent, we need to mark the `UnresolvedLookupExpr` as instantiation dependent in order to correctly build a `DecltypeType` using the expression as its operand with a `DependentDecltypeType` canonical type. Fixes #99873. (cherry picked from commit 55ea36002bd364518c20b3ce282640c920697bf7)
This commit is contained in:
parent
28f2d04b3c
commit
dec94b04c0
@ -3229,7 +3229,7 @@ class UnresolvedLookupExpr final
|
||||
const DeclarationNameInfo &NameInfo, bool RequiresADL,
|
||||
const TemplateArgumentListInfo *TemplateArgs,
|
||||
UnresolvedSetIterator Begin, UnresolvedSetIterator End,
|
||||
bool KnownDependent);
|
||||
bool KnownDependent, bool KnownInstantiationDependent);
|
||||
|
||||
UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults,
|
||||
bool HasTemplateKWAndArgsInfo);
|
||||
@ -3248,7 +3248,7 @@ public:
|
||||
NestedNameSpecifierLoc QualifierLoc,
|
||||
const DeclarationNameInfo &NameInfo, bool RequiresADL,
|
||||
UnresolvedSetIterator Begin, UnresolvedSetIterator End,
|
||||
bool KnownDependent);
|
||||
bool KnownDependent, bool KnownInstantiationDependent);
|
||||
|
||||
// After canonicalization, there may be dependent template arguments in
|
||||
// CanonicalConverted But none of Args is dependent. When any of
|
||||
@ -3258,7 +3258,8 @@ public:
|
||||
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
|
||||
const DeclarationNameInfo &NameInfo, bool RequiresADL,
|
||||
const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin,
|
||||
UnresolvedSetIterator End, bool KnownDependent);
|
||||
UnresolvedSetIterator End, bool KnownDependent,
|
||||
bool KnownInstantiationDependent);
|
||||
|
||||
static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context,
|
||||
unsigned NumResults,
|
||||
|
@ -8578,13 +8578,15 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
|
||||
return UnresolvedLookupExpr::Create(
|
||||
Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr,
|
||||
*ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo,
|
||||
ToDecls.begin(), ToDecls.end(), KnownDependent);
|
||||
ToDecls.begin(), ToDecls.end(), KnownDependent,
|
||||
/*KnownInstantiationDependent=*/E->isInstantiationDependent());
|
||||
}
|
||||
|
||||
return UnresolvedLookupExpr::Create(
|
||||
Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr,
|
||||
ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(),
|
||||
/*KnownDependent=*/E->isTypeDependent());
|
||||
/*KnownDependent=*/E->isTypeDependent(),
|
||||
/*KnownInstantiationDependent=*/E->isInstantiationDependent());
|
||||
}
|
||||
|
||||
ExpectedStmt
|
||||
|
@ -402,10 +402,11 @@ UnresolvedLookupExpr::UnresolvedLookupExpr(
|
||||
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
|
||||
const DeclarationNameInfo &NameInfo, bool RequiresADL,
|
||||
const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin,
|
||||
UnresolvedSetIterator End, bool KnownDependent)
|
||||
UnresolvedSetIterator End, bool KnownDependent,
|
||||
bool KnownInstantiationDependent)
|
||||
: OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc,
|
||||
TemplateKWLoc, NameInfo, TemplateArgs, Begin, End,
|
||||
KnownDependent, false, false),
|
||||
KnownDependent, KnownInstantiationDependent, false),
|
||||
NamingClass(NamingClass) {
|
||||
UnresolvedLookupExprBits.RequiresADL = RequiresADL;
|
||||
}
|
||||
@ -420,7 +421,7 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
|
||||
const ASTContext &Context, CXXRecordDecl *NamingClass,
|
||||
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
|
||||
bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End,
|
||||
bool KnownDependent) {
|
||||
bool KnownDependent, bool KnownInstantiationDependent) {
|
||||
unsigned NumResults = End - Begin;
|
||||
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
|
||||
TemplateArgumentLoc>(NumResults, 0, 0);
|
||||
@ -428,7 +429,8 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
|
||||
return new (Mem) UnresolvedLookupExpr(
|
||||
Context, NamingClass, QualifierLoc,
|
||||
/*TemplateKWLoc=*/SourceLocation(), NameInfo, RequiresADL,
|
||||
/*TemplateArgs=*/nullptr, Begin, End, KnownDependent);
|
||||
/*TemplateArgs=*/nullptr, Begin, End, KnownDependent,
|
||||
KnownInstantiationDependent);
|
||||
}
|
||||
|
||||
UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
|
||||
@ -436,7 +438,8 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
|
||||
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
|
||||
const DeclarationNameInfo &NameInfo, bool RequiresADL,
|
||||
const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin,
|
||||
UnresolvedSetIterator End, bool KnownDependent) {
|
||||
UnresolvedSetIterator End, bool KnownDependent,
|
||||
bool KnownInstantiationDependent) {
|
||||
unsigned NumResults = End - Begin;
|
||||
bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid();
|
||||
unsigned NumTemplateArgs = Args ? Args->size() : 0;
|
||||
@ -444,9 +447,9 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
|
||||
TemplateArgumentLoc>(
|
||||
NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs);
|
||||
void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
|
||||
return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
|
||||
TemplateKWLoc, NameInfo, RequiresADL,
|
||||
Args, Begin, End, KnownDependent);
|
||||
return new (Mem) UnresolvedLookupExpr(
|
||||
Context, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, RequiresADL,
|
||||
Args, Begin, End, KnownDependent, KnownInstantiationDependent);
|
||||
}
|
||||
|
||||
UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty(
|
||||
|
@ -820,7 +820,8 @@ ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc) {
|
||||
Expr *CoawaitOp = UnresolvedLookupExpr::Create(
|
||||
Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
|
||||
DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, Functions.begin(),
|
||||
Functions.end(), /*KnownDependent=*/false);
|
||||
Functions.end(), /*KnownDependent=*/false,
|
||||
/*KnownInstantiationDependent=*/false);
|
||||
assert(CoawaitOp);
|
||||
return CoawaitOp;
|
||||
}
|
||||
|
@ -1219,7 +1219,7 @@ Corrected:
|
||||
return NameClassification::OverloadSet(UnresolvedLookupExpr::Create(
|
||||
Context, Result.getNamingClass(), SS.getWithLocInContext(Context),
|
||||
Result.getLookupNameInfo(), ADL, Result.begin(), Result.end(),
|
||||
/*KnownDependent=*/false));
|
||||
/*KnownDependent=*/false, /*KnownInstantiationDependent=*/false));
|
||||
}
|
||||
|
||||
ExprResult
|
||||
|
@ -1289,7 +1289,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
|
||||
S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(),
|
||||
DeclarationNameInfo(GetDN, Loc), /*RequiresADL=*/true, &Args,
|
||||
UnresolvedSetIterator(), UnresolvedSetIterator(),
|
||||
/*KnownDependent=*/false);
|
||||
/*KnownDependent=*/false, /*KnownInstantiationDependent=*/false);
|
||||
|
||||
Expr *Arg = E.get();
|
||||
E = S.BuildCallExpr(nullptr, Get, Loc, Arg, Loc);
|
||||
|
@ -3188,7 +3188,7 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
|
||||
UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(
|
||||
Context, R.getNamingClass(), SS.getWithLocInContext(Context),
|
||||
R.getLookupNameInfo(), NeedsADL, R.begin(), R.end(),
|
||||
/*KnownDependent=*/false);
|
||||
/*KnownDependent=*/false, /*KnownInstantiationDependent=*/false);
|
||||
|
||||
return ULE;
|
||||
}
|
||||
|
@ -331,7 +331,8 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr(
|
||||
return UnresolvedLookupExpr::Create(
|
||||
Context, R.getNamingClass(), SS.getWithLocInContext(Context),
|
||||
TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false,
|
||||
TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true);
|
||||
TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true,
|
||||
/*KnownInstantiationDependent=*/true);
|
||||
|
||||
case IMA_Error_StaticOrExplicitContext:
|
||||
case IMA_Error_Unrelated:
|
||||
|
@ -17968,7 +17968,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
|
||||
return UnresolvedLookupExpr::Create(
|
||||
SemaRef.Context, /*NamingClass=*/nullptr,
|
||||
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
|
||||
/*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false);
|
||||
/*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
|
||||
/*KnownInstantiationDependent=*/false);
|
||||
}
|
||||
// Lookup inside the classes.
|
||||
// C++ [over.match.oper]p3:
|
||||
@ -20834,7 +20835,8 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
|
||||
return UnresolvedLookupExpr::Create(
|
||||
SemaRef.Context, /*NamingClass=*/nullptr,
|
||||
MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
|
||||
/*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false);
|
||||
/*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
|
||||
/*KnownInstantiationDependent=*/false);
|
||||
}
|
||||
SourceLocation Loc = MapperId.getLoc();
|
||||
// [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
|
||||
|
@ -14083,9 +14083,9 @@ ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
|
||||
DeclarationNameInfo DNI,
|
||||
const UnresolvedSetImpl &Fns,
|
||||
bool PerformADL) {
|
||||
return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI,
|
||||
PerformADL, Fns.begin(), Fns.end(),
|
||||
/*KnownDependent=*/false);
|
||||
return UnresolvedLookupExpr::Create(
|
||||
Context, NamingClass, NNSLoc, DNI, PerformADL, Fns.begin(), Fns.end(),
|
||||
/*KnownDependent=*/false, /*KnownInstantiationDependent=*/false);
|
||||
}
|
||||
|
||||
ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
|
||||
|
@ -4436,7 +4436,8 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
|
||||
UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(
|
||||
Context, R.getNamingClass(), SS.getWithLocInContext(Context),
|
||||
TemplateKWLoc, R.getLookupNameInfo(), RequiresADL, TemplateArgs,
|
||||
R.begin(), R.end(), KnownDependent);
|
||||
R.begin(), R.end(), KnownDependent,
|
||||
/*KnownInstantiationDependent=*/false);
|
||||
|
||||
// Model the templates with UnresolvedTemplateTy. The expression should then
|
||||
// either be transformed in an instantiation or be diagnosed in
|
||||
|
@ -10541,7 +10541,7 @@ TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) {
|
||||
SemaRef.Context, /*NamingClass=*/nullptr,
|
||||
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
|
||||
/*ADL=*/true, Decls.begin(), Decls.end(),
|
||||
/*KnownDependent=*/false));
|
||||
/*KnownDependent=*/false, /*KnownInstantiationDependent=*/false));
|
||||
} else
|
||||
UnresolvedReductions.push_back(nullptr);
|
||||
}
|
||||
@ -10588,7 +10588,7 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause(
|
||||
SemaRef.Context, /*NamingClass=*/nullptr,
|
||||
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
|
||||
/*ADL=*/true, Decls.begin(), Decls.end(),
|
||||
/*KnownDependent=*/false));
|
||||
/*KnownDependent=*/false, /*KnownInstantiationDependent=*/false));
|
||||
} else
|
||||
UnresolvedReductions.push_back(nullptr);
|
||||
}
|
||||
@ -10634,7 +10634,7 @@ TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *C) {
|
||||
SemaRef.Context, /*NamingClass=*/nullptr,
|
||||
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
|
||||
/*ADL=*/true, Decls.begin(), Decls.end(),
|
||||
/*KnownDependent=*/false));
|
||||
/*KnownDependent=*/false, /*KnownInstantiationDependent=*/false));
|
||||
} else
|
||||
UnresolvedReductions.push_back(nullptr);
|
||||
}
|
||||
@ -10816,7 +10816,7 @@ bool transformOMPMappableExprListClause(
|
||||
TT.getSema().Context, /*NamingClass=*/nullptr,
|
||||
MapperIdScopeSpec.getWithLocInContext(TT.getSema().Context),
|
||||
MapperIdInfo, /*ADL=*/true, Decls.begin(), Decls.end(),
|
||||
/*KnownDependent=*/false));
|
||||
/*KnownDependent=*/false, /*KnownInstantiationDependent=*/false));
|
||||
} else {
|
||||
UnresolvedMappers.push_back(nullptr);
|
||||
}
|
||||
|
@ -139,6 +139,31 @@ namespace GH58674 {
|
||||
}
|
||||
}
|
||||
|
||||
namespace GH99873 {
|
||||
struct B {
|
||||
int x;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct A {
|
||||
template<typename U>
|
||||
constexpr int f() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr int f<int>() const {
|
||||
return decltype(B::x)();
|
||||
}
|
||||
};
|
||||
|
||||
// This shouldn't crash.
|
||||
static_assert(A<int>().f<int>() == 0, "");
|
||||
// The result should not be dependent.
|
||||
static_assert(A<int>().f<int>() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A<int>().f<int>() != 0'}}
|
||||
// expected-note@-1 {{expression evaluates to '0 != 0'}}
|
||||
}
|
||||
|
||||
template<typename>
|
||||
class conditional {
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user