Skip to content

Commit b47e439

Browse files
authored
Revert "[Clang][Sema] Fix crash when 'this' is used in a dependent class scope function template specialization that instantiates to a static member function" (#88264)
Reverts #87541
1 parent a2bdbc6 commit b47e439

File tree

8 files changed

+36
-124
lines changed

8 files changed

+36
-124
lines changed

clang/docs/ReleaseNotes.rst

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

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

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5439,8 +5439,7 @@ class Sema final : public SemaBase {
54395439

54405440
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R,
54415441
bool NeedsADL,
5442-
bool AcceptInvalidDecl = false,
5443-
bool NeedUnresolved = false);
5442+
bool AcceptInvalidDecl = false);
54445443
ExprResult BuildDeclarationNameExpr(
54455444
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
54465445
NamedDecl *FoundD = nullptr,
@@ -6592,10 +6591,7 @@ class Sema final : public SemaBase {
65926591
SourceLocation RParenLoc);
65936592

65946593
//// ActOnCXXThis - Parse 'this' pointer.
6595-
ExprResult ActOnCXXThis(SourceLocation Loc);
6596-
6597-
/// Check whether the type of 'this' is valid in the current context.
6598-
bool CheckCXXThisType(SourceLocation Loc, QualType Type);
6594+
ExprResult ActOnCXXThis(SourceLocation loc);
65996595

66006596
/// Build a CXXThisExpr and mark it referenced in the current context.
66016597
Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);

clang/lib/Sema/SemaExpr.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3442,11 +3442,10 @@ static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) {
34423442

34433443
ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
34443444
LookupResult &R, bool NeedsADL,
3445-
bool AcceptInvalidDecl,
3446-
bool NeedUnresolved) {
3445+
bool AcceptInvalidDecl) {
34473446
// If this is a single, fully-resolved result and we don't need ADL,
34483447
// just build an ordinary singleton decl ref.
3449-
if (!NeedUnresolved && !NeedsADL && R.isSingleResult() &&
3448+
if (!NeedsADL && R.isSingleResult() &&
34503449
!R.getAsSingle<FunctionTemplateDecl>() &&
34513450
!ShouldLookupResultBeMultiVersionOverload(R))
34523451
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,42 +1415,26 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
14151415
}
14161416

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

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

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

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

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

14561440
Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type,

clang/lib/Sema/SemaExprMember.cpp

Lines changed: 12 additions & 30 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:
@@ -283,30 +268,27 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr(
283268
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
284269
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
285270
UnresolvedLookupExpr *AsULE) {
286-
switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {
271+
switch (ClassifyImplicitMemberAccess(*this, R)) {
287272
case IMA_Instance:
273+
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);
274+
288275
case IMA_Mixed:
289276
case IMA_Mixed_Unrelated:
290277
case IMA_Unresolved:
291-
return BuildImplicitMemberExpr(
292-
SS, TemplateKWLoc, R, TemplateArgs,
293-
/*IsKnownInstance=*/Classification == IMA_Instance, S);
278+
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
279+
S);
280+
294281
case IMA_Field_Uneval_Context:
295282
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
296283
<< R.getLookupNameInfo().getName();
297284
[[fallthrough]];
298285
case IMA_Static:
299286
case IMA_Abstract:
300-
case IMA_Dependent:
301287
case IMA_Mixed_StaticOrExplicitContext:
302288
case IMA_Unresolved_StaticOrExplicitContext:
303289
if (TemplateArgs || TemplateKWLoc.isValid())
304-
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,
305-
TemplateArgs);
306-
return AsULE ? AsULE
307-
: BuildDeclarationNameExpr(
308-
SS, R, /*NeedsADL=*/false, /*AcceptInvalidDecl=*/false,
309-
/*NeedUnresolved=*/Classification == IMA_Dependent);
290+
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
291+
return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);
310292

311293
case IMA_Error_StaticOrExplicitContext:
312294
case IMA_Error_Unrelated:

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

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

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

clang/lib/Sema/TreeTransform.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3307,13 +3307,12 @@ class TreeTransform {
33073307

33083308
/// Build a new C++ "this" expression.
33093309
///
3310-
/// By default, performs semantic analysis to build a new "this" expression.
3311-
/// Subclasses may override this routine to provide different behavior.
3310+
/// By default, builds a new "this" expression without performing any
3311+
/// semantic analysis. Subclasses may override this routine to provide
3312+
/// different behavior.
33123313
ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
33133314
QualType ThisType,
33143315
bool isImplicit) {
3315-
if (getSema().CheckCXXThisType(ThisLoc, ThisType))
3316-
return ExprError();
33173316
return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit);
33183317
}
33193318

clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp

Lines changed: 3 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
// RUN: %clang_cc1 -fms-extensions -fsyntax-only -Wno-unused-value -verify %s
2-
// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -Wno-unused-value -verify %s
1+
// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s
33

4+
// expected-no-diagnostics
45
class A {
56
public:
67
template<class U> A(U p) {}
@@ -75,42 +76,3 @@ struct S {
7576
int f<0>(int);
7677
};
7778
}
78-
79-
namespace UsesThis {
80-
template<typename T>
81-
struct A {
82-
int x;
83-
84-
template<typename U>
85-
static void f();
86-
87-
template<>
88-
void f<int>() {
89-
this->x; // expected-error {{invalid use of 'this' outside of a non-static member function}}
90-
x; // expected-error {{invalid use of member 'x' in static member function}}
91-
A::x; // expected-error {{invalid use of member 'x' in static member function}}
92-
+x; // expected-error {{invalid use of member 'x' in static member function}}
93-
+A::x; // expected-error {{invalid use of member 'x' in static member function}}
94-
}
95-
96-
template<typename U>
97-
void g();
98-
99-
template<>
100-
void g<int>() {
101-
this->x;
102-
x;
103-
A::x;
104-
+x;
105-
+A::x;
106-
}
107-
108-
template<typename U>
109-
static auto h() -> A*;
110-
111-
template<>
112-
auto h<int>() -> decltype(this); // expected-error {{'this' cannot be used in a static member function declaration}}
113-
};
114-
115-
template struct A<int>; // expected-note 2{{in instantiation of}}
116-
}

0 commit comments

Comments
 (0)