Skip to content

Commit f74be45

Browse files
committed
Reapply "[Clang][Sema] Fix crash when 'this' is used in a dependent class scope function template specialization that instantiates to a static member function (llvm#87541, llvm#88311)"
Reapplies llvm#87541 and llvm#88311 addressing the bug which caused expressions naming overload sets to be incorrectly rebuilt, as well as the bug which caused base class members to always be treated as overload sets.
1 parent 97c60d6 commit f74be45

16 files changed

+376
-124
lines changed

clang/docs/ReleaseNotes.rst

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

534536
- Fix crash when inheriting from a cv-qualified type. Fixes #GH35603
535537
- Fix a crash when the using enum declaration uses an anonymous enumeration. Fixes (#GH86790).

clang/include/clang/AST/ExprCXX.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3219,7 +3219,8 @@ class UnresolvedLookupExpr final
32193219
Create(const ASTContext &Context, CXXRecordDecl *NamingClass,
32203220
NestedNameSpecifierLoc QualifierLoc,
32213221
const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded,
3222-
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
3222+
UnresolvedSetIterator Begin, UnresolvedSetIterator End,
3223+
bool KnownDependent);
32233224

32243225
// After canonicalization, there may be dependent template arguments in
32253226
// CanonicalConverted But none of Args is dependent. When any of

clang/include/clang/Sema/Sema.h

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

54305430
ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R,
54315431
bool NeedsADL,
5432-
bool AcceptInvalidDecl = false);
5432+
bool AcceptInvalidDecl = false,
5433+
bool NeedUnresolved = false);
54335434
ExprResult BuildDeclarationNameExpr(
54345435
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
54355436
NamedDecl *FoundD = nullptr,
@@ -6527,7 +6528,10 @@ class Sema final : public SemaBase {
65276528
SourceLocation RParenLoc);
65286529

65296530
//// ActOnCXXThis - Parse 'this' pointer.
6530-
ExprResult ActOnCXXThis(SourceLocation loc);
6531+
ExprResult ActOnCXXThis(SourceLocation Loc);
6532+
6533+
/// Check whether the type of 'this' is valid in the current context.
6534+
bool CheckCXXThisType(SourceLocation Loc, QualType Type);
65316535

65326536
/// Build a CXXThisExpr and mark it referenced in the current context.
65336537
Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
@@ -6949,10 +6953,14 @@ class Sema final : public SemaBase {
69496953
///@{
69506954

69516955
public:
6956+
/// Check whether an expression might be an implicit class member access.
6957+
bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R,
6958+
bool IsAddressOfOperand);
6959+
69526960
ExprResult BuildPossibleImplicitMemberExpr(
69536961
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
6954-
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
6955-
UnresolvedLookupExpr *AsULE = nullptr);
6962+
const TemplateArgumentListInfo *TemplateArgs, const Scope *S);
6963+
69566964
ExprResult
69576965
BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
69586966
LookupResult &R,

clang/lib/AST/ASTImporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8562,7 +8562,7 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
85628562
return UnresolvedLookupExpr::Create(
85638563
Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr,
85648564
ToNameInfo, E->requiresADL(), E->isOverloaded(), ToDecls.begin(),
8565-
ToDecls.end());
8565+
ToDecls.end(), /*KnownDependent=*/E->isTypeDependent());
85668566
}
85678567

85688568
ExpectedStmt

clang/lib/AST/ExprCXX.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -374,14 +374,15 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create(
374374
const ASTContext &Context, CXXRecordDecl *NamingClass,
375375
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
376376
bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin,
377-
UnresolvedSetIterator End) {
377+
UnresolvedSetIterator End, bool KnownDependent) {
378378
unsigned NumResults = End - Begin;
379379
unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo,
380380
TemplateArgumentLoc>(NumResults, 0, 0);
381381
void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr));
382-
return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc,
383-
SourceLocation(), NameInfo, RequiresADL,
384-
Overloaded, nullptr, Begin, End, false);
382+
return new (Mem) UnresolvedLookupExpr(
383+
Context, NamingClass, QualifierLoc,
384+
/*TemplateKWLoc=*/SourceLocation(), NameInfo, RequiresADL, Overloaded,
385+
/*TemplateArgs=*/nullptr, Begin, End, KnownDependent);
385386
}
386387

387388
UnresolvedLookupExpr *UnresolvedLookupExpr::Create(

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc) {
823823
Expr *CoawaitOp = UnresolvedLookupExpr::Create(
824824
Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
825825
DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded,
826-
Functions.begin(), Functions.end());
826+
Functions.begin(), Functions.end(), /*KnownDependent=*/false);
827827
assert(CoawaitOp);
828828
return CoawaitOp;
829829
}

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1241,7 +1241,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
12411241
return NameClassification::OverloadSet(UnresolvedLookupExpr::Create(
12421242
Context, Result.getNamingClass(), SS.getWithLocInContext(Context),
12431243
Result.getLookupNameInfo(), ADL, Result.isOverloadedResult(),
1244-
Result.begin(), Result.end()));
1244+
Result.begin(), Result.end(), /*KnownDependent=*/false));
12451245
}
12461246

12471247
ExprResult

clang/lib/Sema/SemaExpr.cpp

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

29422925
if (TemplateArgs || TemplateKWLoc.isValid()) {
29432926

@@ -3448,10 +3431,11 @@ static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) {
34483431

34493432
ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
34503433
LookupResult &R, bool NeedsADL,
3451-
bool AcceptInvalidDecl) {
3434+
bool AcceptInvalidDecl,
3435+
bool NeedUnresolved) {
34523436
// If this is a single, fully-resolved result and we don't need ADL,
34533437
// just build an ordinary singleton decl ref.
3454-
if (!NeedsADL && R.isSingleResult() &&
3438+
if (!NeedUnresolved && !NeedsADL && R.isSingleResult() &&
34553439
!R.getAsSingle<FunctionTemplateDecl>() &&
34563440
!ShouldLookupResultBeMultiVersionOverload(R))
34573441
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),
@@ -3471,12 +3455,10 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
34713455
// we've picked a target.
34723456
R.suppressDiagnostics();
34733457

3474-
UnresolvedLookupExpr *ULE
3475-
= UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
3476-
SS.getWithLocInContext(Context),
3477-
R.getLookupNameInfo(),
3478-
NeedsADL, R.isOverloadedResult(),
3479-
R.begin(), R.end());
3458+
UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(
3459+
Context, R.getNamingClass(), SS.getWithLocInContext(Context),
3460+
R.getLookupNameInfo(), NeedsADL, R.isOverloadedResult(), R.begin(),
3461+
R.end(), NeedUnresolved);
34803462

34813463
return ULE;
34823464
}

clang/lib/Sema/SemaExprCXX.cpp

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

14181418
ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
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.
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.
14221423
QualType ThisTy = getCurrentThisType();
14231424

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

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

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

1435-
return Diag(Loc, diag::err_invalid_this_use) << 0;
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;
14361453
}
1437-
1438-
return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false);
1454+
return true;
14391455
}
14401456

14411457
Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type,
@@ -8644,21 +8660,8 @@ static ExprResult attemptRecovery(Sema &SemaRef,
86448660

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

clang/lib/Sema/SemaExprMember.cpp

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

65+
/// Whether the context is static is dependent on the enclosing template (i.e.
66+
/// in a dependent class scope explicit specialization).
67+
IMA_Dependent,
68+
6569
/// The reference may be to an unresolved using declaration and the
6670
/// context is not an instance method.
6771
IMA_Unresolved_StaticOrExplicitContext,
@@ -92,10 +96,18 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
9296

9397
DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
9498

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

100112
if (R.isUnresolvableResult())
101113
return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext
@@ -124,6 +136,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
124136
if (Classes.empty())
125137
return IMA_Static;
126138

139+
if (couldInstantiateToStatic)
140+
return IMA_Dependent;
141+
127142
// C++11 [expr.prim.general]p12:
128143
// An id-expression that denotes a non-static data member or non-static
129144
// member function of a class can only be used:
@@ -264,32 +279,52 @@ static void diagnoseInstanceReference(Sema &SemaRef,
264279
}
265280
}
266281

282+
bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS,
283+
LookupResult &R,
284+
bool IsAddressOfOperand) {
285+
if (!getLangOpts().CPlusPlus)
286+
return false;
287+
else if (R.empty() || !R.begin()->isCXXClassMember())
288+
return false;
289+
else if (!IsAddressOfOperand)
290+
return true;
291+
else if (!SS.isEmpty())
292+
return false;
293+
else if (R.isOverloadedResult())
294+
return false;
295+
else if (R.isUnresolvableResult())
296+
return true;
297+
else
298+
return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl());
299+
}
300+
267301
/// Builds an expression which might be an implicit member expression.
268302
ExprResult Sema::BuildPossibleImplicitMemberExpr(
269303
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
270-
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
271-
UnresolvedLookupExpr *AsULE) {
272-
switch (ClassifyImplicitMemberAccess(*this, R)) {
304+
const TemplateArgumentListInfo *TemplateArgs, const Scope *S) {
305+
switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {
273306
case IMA_Instance:
274-
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);
275-
276307
case IMA_Mixed:
277308
case IMA_Mixed_Unrelated:
278309
case IMA_Unresolved:
279-
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
280-
S);
281-
310+
return BuildImplicitMemberExpr(
311+
SS, TemplateKWLoc, R, TemplateArgs,
312+
/*IsKnownInstance=*/Classification == IMA_Instance, S);
282313
case IMA_Field_Uneval_Context:
283314
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
284315
<< R.getLookupNameInfo().getName();
285316
[[fallthrough]];
286317
case IMA_Static:
287318
case IMA_Abstract:
319+
case IMA_Dependent:
288320
case IMA_Mixed_StaticOrExplicitContext:
289321
case IMA_Unresolved_StaticOrExplicitContext:
290322
if (TemplateArgs || TemplateKWLoc.isValid())
291-
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
292-
return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);
323+
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,
324+
TemplateArgs);
325+
return BuildDeclarationNameExpr(
326+
SS, R, /*NeedsADL=*/false, /*AcceptInvalidDecl=*/false,
327+
/*NeedUnresolved=*/Classification == IMA_Dependent);
293328

294329
case IMA_Error_StaticOrExplicitContext:
295330
case IMA_Error_Unrelated:

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19354,7 +19354,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
1935419354
return UnresolvedLookupExpr::Create(
1935519355
SemaRef.Context, /*NamingClass=*/nullptr,
1935619356
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19357-
/*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
19357+
/*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end(),
19358+
/*KnownDependent=*/false);
1935819359
}
1935919360
// Lookup inside the classes.
1936019361
// C++ [over.match.oper]p3:
@@ -22220,7 +22221,8 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
2222022221
return UnresolvedLookupExpr::Create(
2222122222
SemaRef.Context, /*NamingClass=*/nullptr,
2222222223
MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22223-
/*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
22224+
/*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end(),
22225+
/*KnownDependent=*/false);
2222422226
}
2222522227
SourceLocation Loc = MapperId.getLoc();
2222622228
// [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions

clang/lib/Sema/SemaOverload.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14271,7 +14271,8 @@ ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
1427114271
bool PerformADL) {
1427214272
return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI,
1427314273
PerformADL, IsOverloaded(Fns),
14274-
Fns.begin(), Fns.end());
14274+
Fns.begin(), Fns.end(),
14275+
/*KnownDependent=*/false);
1427514276
}
1427614277

1427714278
ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

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

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

0 commit comments

Comments
 (0)