Skip to content

Commit 46131aa

Browse files
committed
Revert "Reapply "[Clang][Sema] Fix crash when 'this' is used in a dependent class scope function template specialization that instantiates to a static member function (#87541)" (#88311)"
This reverts commit aa80f3e. See #88311 (comment). There is a fix forward proposed but I am reverting this commit to fix trunk.
1 parent 2cc0c21 commit 46131aa

9 files changed

+99
-252
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,8 +529,6 @@ Bug Fixes to C++ Support
529529
- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757).
530530
- Fixed a bug that prevented member function templates of class templates declared with a deduced return type
531531
from being explicitly specialized for a given implicit instantiation of the class template.
532-
- Fixed a crash when ``this`` is used in a dependent class scope function template specialization
533-
that instantiates to a static member function.
534532

535533
- Fix crash when inheriting from a cv-qualified type. Fixes:
536534
(`#35603 <https://github.com/llvm/llvm-project/issues/35603>`_)

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5452,8 +5452,7 @@ class Sema final : public SemaBase {
54525452

54535453
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R,
54545454
bool NeedsADL,
5455-
bool AcceptInvalidDecl = false,
5456-
bool NeedUnresolved = false);
5455+
bool AcceptInvalidDecl = false);
54575456
ExprResult BuildDeclarationNameExpr(
54585457
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
54595458
NamedDecl *FoundD = nullptr,
@@ -6596,10 +6595,7 @@ class Sema final : public SemaBase {
65966595
SourceLocation RParenLoc);
65976596

65986597
//// ActOnCXXThis - Parse 'this' pointer.
6599-
ExprResult ActOnCXXThis(SourceLocation Loc);
6600-
6601-
/// Check whether the type of 'this' is valid in the current context.
6602-
bool CheckCXXThisType(SourceLocation Loc, QualType Type);
6598+
ExprResult ActOnCXXThis(SourceLocation loc);
66036599

66046600
/// Build a CXXThisExpr and mark it referenced in the current context.
66056601
Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
@@ -7022,14 +7018,10 @@ class Sema final : public SemaBase {
70227018
///@{
70237019

70247020
public:
7025-
/// Check whether an expression might be an implicit class member access.
7026-
bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R,
7027-
bool IsAddressOfOperand);
7028-
70297021
ExprResult BuildPossibleImplicitMemberExpr(
70307022
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
7031-
const TemplateArgumentListInfo *TemplateArgs, const Scope *S);
7032-
7023+
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
7024+
UnresolvedLookupExpr *AsULE = nullptr);
70337025
ExprResult
70347026
BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
70357027
LookupResult &R,

clang/lib/Sema/SemaExpr.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2917,9 +2917,26 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
29172917
// to get this right here so that we don't end up making a
29182918
// spuriously dependent expression if we're inside a dependent
29192919
// instance method.
2920-
if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand))
2921-
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs,
2922-
S);
2920+
if (getLangOpts().CPlusPlus && !R.empty() &&
2921+
(*R.begin())->isCXXClassMember()) {
2922+
bool MightBeImplicitMember;
2923+
if (!IsAddressOfOperand)
2924+
MightBeImplicitMember = true;
2925+
else if (!SS.isEmpty())
2926+
MightBeImplicitMember = false;
2927+
else if (R.isOverloadedResult())
2928+
MightBeImplicitMember = false;
2929+
else if (R.isUnresolvableResult())
2930+
MightBeImplicitMember = true;
2931+
else
2932+
MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
2933+
isa<IndirectFieldDecl>(R.getFoundDecl()) ||
2934+
isa<MSPropertyDecl>(R.getFoundDecl());
2935+
2936+
if (MightBeImplicitMember)
2937+
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
2938+
R, TemplateArgs, S);
2939+
}
29232940

29242941
if (TemplateArgs || TemplateKWLoc.isValid()) {
29252942

@@ -3430,11 +3447,10 @@ static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) {
34303447

34313448
ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
34323449
LookupResult &R, bool NeedsADL,
3433-
bool AcceptInvalidDecl,
3434-
bool NeedUnresolved) {
3450+
bool AcceptInvalidDecl) {
34353451
// If this is a single, fully-resolved result and we don't need ADL,
34363452
// just build an ordinary singleton decl ref.
3437-
if (!NeedUnresolved && !NeedsADL && R.isSingleResult() &&
3453+
if (!NeedsADL && R.isSingleResult() &&
34383454
!R.getAsSingle<FunctionTemplateDecl>() &&
34393455
!ShouldLookupResultBeMultiVersionOverload(R))
34403456
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,42 +1416,26 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
14161416
}
14171417

14181418
ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
1419-
// C++20 [expr.prim.this]p1:
1420-
// The keyword this names a pointer to the object for which an
1421-
// implicit object member function is invoked or a non-static
1422-
// data member's initializer is evaluated.
1419+
/// C++ 9.3.2: In the body of a non-static member function, the keyword this
1420+
/// is a non-lvalue expression whose value is the address of the object for
1421+
/// which the function is called.
14231422
QualType ThisTy = getCurrentThisType();
14241423

1425-
if (CheckCXXThisType(Loc, ThisTy))
1426-
return ExprError();
1424+
if (ThisTy.isNull()) {
1425+
DeclContext *DC = getFunctionLevelDeclContext();
14271426

1428-
return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false);
1429-
}
1427+
if (const auto *Method = dyn_cast<CXXMethodDecl>(DC);
1428+
Method && Method->isExplicitObjectMemberFunction()) {
1429+
return Diag(Loc, diag::err_invalid_this_use) << 1;
1430+
}
14301431

1431-
bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) {
1432-
if (!Type.isNull())
1433-
return false;
1432+
if (isLambdaCallWithExplicitObjectParameter(CurContext))
1433+
return Diag(Loc, diag::err_invalid_this_use) << 1;
14341434

1435-
// C++20 [expr.prim.this]p3:
1436-
// If a declaration declares a member function or member function template
1437-
// of a class X, the expression this is a prvalue of type
1438-
// "pointer to cv-qualifier-seq X" wherever X is the current class between
1439-
// the optional cv-qualifier-seq and the end of the function-definition,
1440-
// member-declarator, or declarator. It shall not appear within the
1441-
// declaration of either a static member function or an explicit object
1442-
// member function of the current class (although its type and value
1443-
// category are defined within such member functions as they are within
1444-
// an implicit object member function).
1445-
DeclContext *DC = getFunctionLevelDeclContext();
1446-
if (const auto *Method = dyn_cast<CXXMethodDecl>(DC);
1447-
Method && Method->isExplicitObjectMemberFunction()) {
1448-
Diag(Loc, diag::err_invalid_this_use) << 1;
1449-
} else if (isLambdaCallWithExplicitObjectParameter(CurContext)) {
1450-
Diag(Loc, diag::err_invalid_this_use) << 1;
1451-
} else {
1452-
Diag(Loc, diag::err_invalid_this_use) << 0;
1435+
return Diag(Loc, diag::err_invalid_this_use) << 0;
14531436
}
1454-
return true;
1437+
1438+
return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false);
14551439
}
14561440

14571441
Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type,
@@ -8658,8 +8642,21 @@ static ExprResult attemptRecovery(Sema &SemaRef,
86588642

86598643
// Detect and handle the case where the decl might be an implicit
86608644
// member.
8661-
if (SemaRef.isPotentialImplicitMemberAccess(
8662-
NewSS, R, Consumer.isAddressOfOperand()))
8645+
bool MightBeImplicitMember;
8646+
if (!Consumer.isAddressOfOperand())
8647+
MightBeImplicitMember = true;
8648+
else if (!NewSS.isEmpty())
8649+
MightBeImplicitMember = false;
8650+
else if (R.isOverloadedResult())
8651+
MightBeImplicitMember = false;
8652+
else if (R.isUnresolvableResult())
8653+
MightBeImplicitMember = true;
8654+
else
8655+
MightBeImplicitMember = isa<FieldDecl>(ND) ||
8656+
isa<IndirectFieldDecl>(ND) ||
8657+
isa<MSPropertyDecl>(ND);
8658+
8659+
if (MightBeImplicitMember)
86638660
return SemaRef.BuildPossibleImplicitMemberExpr(
86648661
NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
86658662
/*TemplateArgs*/ nullptr, /*S*/ nullptr);

clang/lib/Sema/SemaExprMember.cpp

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ enum IMAKind {
6161
/// The reference is a contextually-permitted abstract member reference.
6262
IMA_Abstract,
6363

64-
/// Whether the context is static is dependent on the enclosing template (i.e.
65-
/// in a dependent class scope explicit specialization).
66-
IMA_Dependent,
67-
6864
/// The reference may be to an unresolved using declaration and the
6965
/// context is not an instance method.
7066
IMA_Unresolved_StaticOrExplicitContext,
@@ -95,18 +91,10 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
9591

9692
DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
9793

98-
bool couldInstantiateToStatic = false;
99-
bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull();
100-
101-
if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) {
102-
if (MD->isImplicitObjectMemberFunction()) {
103-
isStaticOrExplicitContext = false;
104-
// A dependent class scope function template explicit specialization
105-
// that is neither declared 'static' nor with an explicit object
106-
// parameter could instantiate to a static or non-static member function.
107-
couldInstantiateToStatic = MD->getDependentSpecializationInfo();
108-
}
109-
}
94+
bool isStaticOrExplicitContext =
95+
SemaRef.CXXThisTypeOverride.isNull() &&
96+
(!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic() ||
97+
cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction());
11098

11199
if (R.isUnresolvableResult())
112100
return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext
@@ -135,9 +123,6 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
135123
if (Classes.empty())
136124
return IMA_Static;
137125

138-
if (couldInstantiateToStatic)
139-
return IMA_Dependent;
140-
141126
// C++11 [expr.prim.general]p12:
142127
// An id-expression that denotes a non-static data member or non-static
143128
// member function of a class can only be used:
@@ -278,52 +263,32 @@ static void diagnoseInstanceReference(Sema &SemaRef,
278263
}
279264
}
280265

281-
bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS,
282-
LookupResult &R,
283-
bool IsAddressOfOperand) {
284-
if (!getLangOpts().CPlusPlus)
285-
return false;
286-
else if (R.empty() || !R.begin()->isCXXClassMember())
287-
return false;
288-
else if (!IsAddressOfOperand)
289-
return true;
290-
else if (!SS.isEmpty())
291-
return false;
292-
else if (R.isOverloadedResult())
293-
return false;
294-
else if (R.isUnresolvableResult())
295-
return true;
296-
else
297-
return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl());
298-
}
299-
300266
/// Builds an expression which might be an implicit member expression.
301267
ExprResult Sema::BuildPossibleImplicitMemberExpr(
302268
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
303-
const TemplateArgumentListInfo *TemplateArgs, const Scope *S) {
304-
switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {
269+
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
270+
UnresolvedLookupExpr *AsULE) {
271+
switch (ClassifyImplicitMemberAccess(*this, R)) {
305272
case IMA_Instance:
273+
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);
274+
306275
case IMA_Mixed:
307276
case IMA_Mixed_Unrelated:
308277
case IMA_Unresolved:
309-
return BuildImplicitMemberExpr(
310-
SS, TemplateKWLoc, R, TemplateArgs,
311-
/*IsKnownInstance=*/Classification == IMA_Instance, S);
278+
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
279+
S);
280+
312281
case IMA_Field_Uneval_Context:
313282
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
314283
<< R.getLookupNameInfo().getName();
315284
[[fallthrough]];
316285
case IMA_Static:
317286
case IMA_Abstract:
318-
case IMA_Dependent:
319287
case IMA_Mixed_StaticOrExplicitContext:
320288
case IMA_Unresolved_StaticOrExplicitContext:
321289
if (TemplateArgs || TemplateKWLoc.isValid())
322-
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,
323-
TemplateArgs);
324-
return BuildDeclarationNameExpr(
325-
SS, R, /*NeedsADL=*/false, /*AcceptInvalidDecl=*/false,
326-
/*NeedUnresolved=*/Classification == IMA_Dependent);
290+
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
291+
return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);
327292

328293
case IMA_Error_StaticOrExplicitContext:
329294
case IMA_Error_Unrelated:

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5097,14 +5097,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
50975097
EnterExpressionEvaluationContext EvalContext(
50985098
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
50995099

5100-
Qualifiers ThisTypeQuals;
5101-
CXXRecordDecl *ThisContext = nullptr;
5102-
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
5103-
ThisContext = Method->getParent();
5104-
ThisTypeQuals = Method->getMethodQualifiers();
5105-
}
5106-
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals);
5107-
51085100
// Introduce a new scope where local variable instantiations will be
51095101
// recorded, unless we're actually a member function within a local
51105102
// class, in which case we need to merge our results with the parent

0 commit comments

Comments
 (0)