Skip to content

Commit a46f2d0

Browse files
sdkrystianaaryanshukla
authored andcommitted
[Clang] Implement resolution for CWG1835 (llvm#92957)
CWG1835 was one of the many core issues resolved by P1787R6: "Declarations and where to find them" (http://wg21.link/p1787r6). Its resolution changes how member-qualified names (as defined by [basic.lookup.qual.general] p2) are looked up. This patch implementation that resolution. Previously, an _identifier_ following `.` or `->` would be first looked up in the type of the object expression (i.e. qualified lookup), and then in the context of the _postfix-expression_ (i.e. unqualified lookup) if nothing was found; the result of the second lookup was required to name a class template. Notably, this second lookup would occur even when the object expression was dependent, and its result would be used to determine whether a `<` token is the start of a _template-argument_list_. The new wording in [basic.lookup.qual.general] p2 states: > A member-qualified name is the (unique) component name, if any, of > - an _unqualified-id_ or > - a _nested-name-specifier_ of the form _`type-name ::`_ or _`namespace-name ::`​_ > > in the id-expression of a class member access expression. A ***qualified name*** is > - a member-qualified name or > - the terminal name of > - a _qualified-id_, > - a _using-declarator_, > - a _typename-specifier_, > - a _qualified-namespace-specifier_, or > - a _nested-name-specifier_, _elaborated-type-specifier_, or _class-or-decltype_ that has a _nested-name-specifier_. > > The _lookup context_ of a member-qualified name is the type of its associated object expression (considered dependent if the object expression is type-dependent). The lookup context of any other qualified name is the type, template, or namespace nominated by the preceding _nested-name-specifier_. And [basic.lookup.qual.general] p3 now states: > _Qualified name lookup_ in a class, namespace, or enumeration performs a search of the scope associated with it except as specified below. Unless otherwise specified, a qualified name undergoes qualified name lookup in its lookup context from the point where it appears unless the lookup context either is dependent and is not the current instantiation or is not a class or class template. If nothing is found by qualified lookup for a member-qualified name that is the terminal name of a _nested-name-specifier_ and is not dependent, it undergoes unqualified lookup. In non-standardese terms, these two paragraphs essentially state the following: - A name that immediately follows `.` or `->` in a class member access expression is a member-qualified name - A member-qualified name will be first looked up in the type of the object expression `T` unless `T` is a dependent type that is _not_ the current instantiation, e.g. ``` template<typename T> struct A { void f(T* t) { this->x; // type of the object expression is 'A<T>'. although 'A<T>' is dependent, it is the // current instantiation so we look up 'x' in the template definition context. t->y; // type of the object expression is 'T' ('->' is transformed to '.' per [expr.ref]). // 'T' is dependent and is *not* the current instantiation, so we lookup 'y' in the // template instantiation context. } }; ``` - If the first lookup finds nothing and: - the member-qualified name is the first component of a _nested-name-specifier_ (which could be an _identifier_ or a _simple-template-id_), and either: - the type of the object expression is the current instantiation and it has no dependent base classes, or - the type of the object expression is not dependent then we lookup the name again, this time via unqualified lookup. Although the second (unqualified) lookup is stated not to occur when the member-qualified name is dependent, a dependent name will _not_ be dependent once the template is instantiated, so the second lookup must "occur" during instantiation if qualified lookup does not find anything. This means that we must perform the second (unqualified) lookup during parsing even when the type of the object expression is dependent, but those results are _not_ used to determine whether a `<` token is the start of a _template-argument_list_; they are stored so we can replicate the second lookup during instantiation. In even simpler terms (paraphrasing the meeting minutes from the review of P1787; see https://wiki.edg.com/bin/view/Wg21summer2020/P1787%28Lookup%29Review2020-06-15Through2020-06-18): - Unqualified lookup always happens for the first name in a _nested-name-specifier_ that follows `.` or `->` - The result of that lookup is only used to determine whether `<` is the start of a _template-argument-list_ if the first (qualified) lookup found nothing and the lookup context: - is not dependent, or - is the current instantiation and has no dependent base classes. An example: ``` struct A { void f(); }; template<typename T> using B = A; template<typename T> struct C : A { template<typename U> void g(); void h(T* t) { this->g<int>(); // ok, '<' is the start of a template-argument-list ('g' was found via qualified lookup in the current instantiation) this->B<void>::f(); // ok, '<' is the start of a template-argument-list (current instantiation has no dependent bases, 'B' was found via unqualified lookup) t->g<int>(); // error: '<' means less than (unqualified lookup does not occur for a member-qualified name that isn't the first component of a nested-name-specifier) t->B<void>::f(); // error: '<' means less than (unqualified lookup does not occur if the name is dependent) t->template B<void>::f(); // ok: '<' is the start of a template-argument-list ('template' keyword used) } }; ``` Some additional notes: - Per [basic.lookup.qual.general] p1, lookup for a member-qualified name only considers namespaces, types, and templates whose specializations are types if it's an _identifier_ followed by `::`; lookup for the component name of a _simple-template-id_ followed by `::` is _not_ subject to this rule. - The wording which specifies when the second unqualified lookup occurs appears to be paradoxical. We are supposed to do it only for the first component name of a _nested-name-specifier_ that follows `.` or `->` when qualified lookup finds nothing. However, when that name is followed by `<` (potentially starting a _simple-template-id_) we don't _know_ whether it will be the start of a _nested-name-specifier_ until we do the lookup -- but we aren't supposed to do the lookup until we know it's part of a _nested-name-specifier_! ***However***, since we only do the second lookup when the first lookup finds nothing (and the name isn't dependent), ***and*** since neither lookup is type-only, the only valid option is for the name to be the _template-name_ in a _simple-template-id_ that is followed by `::` (it can't be an _unqualified-id_ naming a member because we already determined that the lookup context doesn't have a member with that name). Thus, we can lock into the _nested-name-specifier_ interpretation and do the second lookup without having to know whether the _simple-template-id_ will be followed by `::` yet.
1 parent 1bd7d3c commit a46f2d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1113
-811
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ Resolutions to C++ Defect Reports
306306
- Clang now considers ``noexcept(typeid(expr))`` more carefully, instead of always assuming that ``std::bad_typeid`` can be thrown.
307307
(`CWG2191: Incorrect result for noexcept(typeid(v)) <https://cplusplus.github.io/CWG/issues/2191.html>`_).
308308

309+
- Clang now correctly implements lookup for the terminal name of a member-qualified nested-name-specifier.
310+
(`CWG1835: Dependent member lookup before < <https://cplusplus.github.io/CWG/issues/1835.html>`_).
311+
309312
C Language Changes
310313
------------------
311314

clang/include/clang/AST/ExprCXX.h

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3676,9 +3676,9 @@ class CXXUnresolvedConstructExpr final
36763676
/// an implicit access if a qualifier is provided.
36773677
class CXXDependentScopeMemberExpr final
36783678
: public Expr,
3679-
private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
3680-
ASTTemplateKWAndArgsInfo,
3681-
TemplateArgumentLoc, NamedDecl *> {
3679+
private llvm::TrailingObjects<
3680+
CXXDependentScopeMemberExpr, NestedNameSpecifierLoc, DeclAccessPair,
3681+
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
36823682
friend class ASTStmtReader;
36833683
friend class ASTStmtWriter;
36843684
friend TrailingObjects;
@@ -3691,17 +3691,15 @@ class CXXDependentScopeMemberExpr final
36913691
/// implicit accesses.
36923692
QualType BaseType;
36933693

3694-
/// The nested-name-specifier that precedes the member name, if any.
3695-
/// FIXME: This could be in principle store as a trailing object.
3696-
/// However the performance impact of doing so should be investigated first.
3697-
NestedNameSpecifierLoc QualifierLoc;
3698-
36993694
/// The member to which this member expression refers, which
37003695
/// can be name, overloaded operator, or destructor.
37013696
///
37023697
/// FIXME: could also be a template-id
37033698
DeclarationNameInfo MemberNameInfo;
37043699

3700+
/// The location of the '->' or '.' operator.
3701+
SourceLocation OperatorLoc;
3702+
37053703
// CXXDependentScopeMemberExpr is followed by several trailing objects,
37063704
// some of which optional. They are in order:
37073705
//
@@ -3721,8 +3719,16 @@ class CXXDependentScopeMemberExpr final
37213719
return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo;
37223720
}
37233721

3724-
bool hasFirstQualifierFoundInScope() const {
3725-
return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope;
3722+
unsigned getNumUnqualifiedLookups() const {
3723+
return CXXDependentScopeMemberExprBits.NumUnqualifiedLookups;
3724+
}
3725+
3726+
unsigned numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
3727+
return hasQualifier();
3728+
}
3729+
3730+
unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const {
3731+
return getNumUnqualifiedLookups();
37263732
}
37273733

37283734
unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
@@ -3733,33 +3739,32 @@ class CXXDependentScopeMemberExpr final
37333739
return getNumTemplateArgs();
37343740
}
37353741

3736-
unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const {
3737-
return hasFirstQualifierFoundInScope();
3738-
}
3739-
37403742
CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base,
37413743
QualType BaseType, bool IsArrow,
37423744
SourceLocation OperatorLoc,
37433745
NestedNameSpecifierLoc QualifierLoc,
37443746
SourceLocation TemplateKWLoc,
3745-
NamedDecl *FirstQualifierFoundInScope,
3747+
ArrayRef<DeclAccessPair> UnqualifiedLookups,
37463748
DeclarationNameInfo MemberNameInfo,
37473749
const TemplateArgumentListInfo *TemplateArgs);
37483750

3749-
CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
3750-
bool HasFirstQualifierFoundInScope);
3751+
CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasQualifier,
3752+
unsigned NumUnqualifiedLookups,
3753+
bool HasTemplateKWAndArgsInfo);
37513754

37523755
public:
37533756
static CXXDependentScopeMemberExpr *
37543757
Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
37553758
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
3756-
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
3759+
SourceLocation TemplateKWLoc,
3760+
ArrayRef<DeclAccessPair> UnqualifiedLookups,
37573761
DeclarationNameInfo MemberNameInfo,
37583762
const TemplateArgumentListInfo *TemplateArgs);
37593763

37603764
static CXXDependentScopeMemberExpr *
3761-
CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
3762-
unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope);
3765+
CreateEmpty(const ASTContext &Ctx, bool HasQualifier,
3766+
unsigned NumUnqualifiedLookups, bool HasTemplateKWAndArgsInfo,
3767+
unsigned NumTemplateArgs);
37633768

37643769
/// True if this is an implicit access, i.e. one in which the
37653770
/// member being accessed was not written in the source. The source
@@ -3784,34 +3789,35 @@ class CXXDependentScopeMemberExpr final
37843789
bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; }
37853790

37863791
/// Retrieve the location of the '->' or '.' operator.
3787-
SourceLocation getOperatorLoc() const {
3788-
return CXXDependentScopeMemberExprBits.OperatorLoc;
3792+
SourceLocation getOperatorLoc() const { return OperatorLoc; }
3793+
3794+
/// Determines whether this member expression had a nested-name-specifier
3795+
/// prior to the name of the member, e.g., x->Base::foo.
3796+
bool hasQualifier() const {
3797+
return CXXDependentScopeMemberExprBits.HasQualifier;
37893798
}
37903799

3791-
/// Retrieve the nested-name-specifier that qualifies the member name.
3792-
NestedNameSpecifier *getQualifier() const {
3793-
return QualifierLoc.getNestedNameSpecifier();
3800+
/// If the member name was qualified, retrieves the nested-name-specifier
3801+
/// that precedes the member name, with source-location information.
3802+
NestedNameSpecifierLoc getQualifierLoc() const {
3803+
if (!hasQualifier())
3804+
return NestedNameSpecifierLoc();
3805+
return *getTrailingObjects<NestedNameSpecifierLoc>();
37943806
}
37953807

3796-
/// Retrieve the nested-name-specifier that qualifies the member
3797-
/// name, with source location information.
3798-
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
3808+
/// If the member name was qualified, retrieves the
3809+
/// nested-name-specifier that precedes the member name. Otherwise, returns
3810+
/// NULL.
3811+
NestedNameSpecifier *getQualifier() const {
3812+
return getQualifierLoc().getNestedNameSpecifier();
3813+
}
37993814

3800-
/// Retrieve the first part of the nested-name-specifier that was
3801-
/// found in the scope of the member access expression when the member access
3802-
/// was initially parsed.
3803-
///
3804-
/// This function only returns a useful result when member access expression
3805-
/// uses a qualified member name, e.g., "x.Base::f". Here, the declaration
3806-
/// returned by this function describes what was found by unqualified name
3807-
/// lookup for the identifier "Base" within the scope of the member access
3808-
/// expression itself. At template instantiation time, this information is
3809-
/// combined with the results of name lookup into the type of the object
3810-
/// expression itself (the class type of x).
3811-
NamedDecl *getFirstQualifierFoundInScope() const {
3812-
if (!hasFirstQualifierFoundInScope())
3813-
return nullptr;
3814-
return *getTrailingObjects<NamedDecl *>();
3815+
/// Retrieve the declarations found by unqualified lookup for the first
3816+
/// component name of the nested-name-specifier, if any.
3817+
ArrayRef<DeclAccessPair> unqualified_lookups() const {
3818+
if (!getNumUnqualifiedLookups())
3819+
return std::nullopt;
3820+
return {getTrailingObjects<DeclAccessPair>(), getNumUnqualifiedLookups()};
38153821
}
38163822

38173823
/// Retrieve the name of the member that this expression refers to.

clang/include/clang/AST/Stmt.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,18 +1020,19 @@ class alignas(void *) Stmt {
10201020
LLVM_PREFERRED_TYPE(bool)
10211021
unsigned IsArrow : 1;
10221022

1023+
/// True if this member expression used a nested-name-specifier to
1024+
/// refer to the member, e.g., "x->Base::f".
1025+
LLVM_PREFERRED_TYPE(bool)
1026+
unsigned HasQualifier : 1;
1027+
10231028
/// Whether this member expression has info for explicit template
10241029
/// keyword and arguments.
10251030
LLVM_PREFERRED_TYPE(bool)
10261031
unsigned HasTemplateKWAndArgsInfo : 1;
10271032

1028-
/// See getFirstQualifierFoundInScope() and the comment listing
1029-
/// the trailing objects.
1030-
LLVM_PREFERRED_TYPE(bool)
1031-
unsigned HasFirstQualifierFoundInScope : 1;
1032-
1033-
/// The location of the '->' or '.' operator.
1034-
SourceLocation OperatorLoc;
1033+
/// Number of declarations found by unqualified lookup for the
1034+
/// first component name of the nested-name-specifier.
1035+
unsigned NumUnqualifiedLookups;
10351036
};
10361037

10371038
class OverloadExprBitfields {

clang/include/clang/AST/UnresolvedSet.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ class UnresolvedSetImpl {
9797
decls().push_back(DeclAccessPair::make(D, AS));
9898
}
9999

100+
void addAllDecls(ArrayRef<DeclAccessPair> Other) {
101+
append(iterator(Other.begin()), iterator(Other.end()));
102+
}
103+
100104
/// Replaces the given declaration with the new one, once.
101105
///
102106
/// \return true if the set changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -895,9 +895,7 @@ def missing_template_arg_list_after_template_kw : Extension<
895895
"keyword">, InGroup<DiagGroup<"missing-template-arg-list-after-template-kw">>,
896896
DefaultError;
897897

898-
def err_missing_dependent_template_keyword : Error<
899-
"use 'template' keyword to treat '%0' as a dependent template name">;
900-
def warn_missing_dependent_template_keyword : ExtWarn<
898+
def ext_missing_dependent_template_keyword : ExtWarn<
901899
"use 'template' keyword to treat '%0' as a dependent template name">;
902900

903901
def ext_extern_template : Extension<

clang/include/clang/Parse/Parser.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3368,15 +3368,11 @@ class Parser : public CodeCompletionHandler {
33683368
BaseResult ParseBaseSpecifier(Decl *ClassDecl);
33693369
AccessSpecifier getAccessSpecifierIfPresent() const;
33703370

3371-
bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
3372-
ParsedType ObjectType,
3373-
bool ObjectHadErrors,
3374-
SourceLocation TemplateKWLoc,
3375-
IdentifierInfo *Name,
3376-
SourceLocation NameLoc,
3377-
bool EnteringContext,
3378-
UnqualifiedId &Id,
3379-
bool AssumeTemplateId);
3371+
bool ParseUnqualifiedIdTemplateId(
3372+
CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
3373+
SourceLocation TemplateKWLoc, SourceLocation TildeLoc,
3374+
IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext,
3375+
UnqualifiedId &Id, bool AssumeTemplateId);
33803376
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
33813377
ParsedType ObjectType,
33823378
UnqualifiedId &Result);

clang/include/clang/Sema/DeclSpec.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class CXXScopeSpec {
7575
SourceRange Range;
7676
NestedNameSpecifierLocBuilder Builder;
7777
ArrayRef<TemplateParameterList *> TemplateParamLists;
78+
ArrayRef<DeclAccessPair> UnqualifiedLookups;
7879

7980
public:
8081
SourceRange getRange() const { return Range; }
@@ -91,6 +92,13 @@ class CXXScopeSpec {
9192
return TemplateParamLists;
9293
}
9394

95+
void setUnqualifiedLookups(ArrayRef<DeclAccessPair> Found) {
96+
UnqualifiedLookups = Found;
97+
}
98+
ArrayRef<DeclAccessPair> getUnqualifiedLookups() const {
99+
return UnqualifiedLookups;
100+
}
101+
94102
/// Retrieve the representation of the nested-name-specifier.
95103
NestedNameSpecifier *getScopeRep() const {
96104
return Builder.getRepresentation();

clang/include/clang/Sema/Lookup.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,15 @@ class LookupResult {
483483
ResultKind = Found;
484484
}
485485

486+
void addAllDecls(ArrayRef<DeclAccessPair> Other) {
487+
Decls.addAllDecls(Other);
488+
ResultKind = Found;
489+
}
490+
486491
/// Add all the declarations from another set of lookup
487492
/// results.
488493
void addAllDecls(const LookupResult &Other) {
489-
Decls.append(Other.Decls.begin(), Other.Decls.end());
490-
ResultKind = Found;
494+
addAllDecls(Other.Decls.pairs());
491495
}
492496

493497
/// Determine whether no result was found because we could not

clang/include/clang/Sema/Sema.h

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,7 +2802,8 @@ class Sema final : public SemaBase {
28022802
/// (e.g., Base::), perform name lookup for that identifier as a
28032803
/// nested-name-specifier within the given scope, and return the result of
28042804
/// that name lookup.
2805-
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
2805+
bool LookupFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS,
2806+
UnresolvedSetImpl &R);
28062807

28072808
/// Keeps information about an identifier in a nested-name-spec.
28082809
///
@@ -2842,9 +2843,6 @@ class Sema final : public SemaBase {
28422843
/// \param EnteringContext If true, enter the context specified by the
28432844
/// nested-name-specifier.
28442845
/// \param SS Optional nested name specifier preceding the identifier.
2845-
/// \param ScopeLookupResult Provides the result of name lookup within the
2846-
/// scope of the nested-name-specifier that was computed at template
2847-
/// definition time.
28482846
/// \param ErrorRecoveryLookup Specifies if the method is called to improve
28492847
/// error recovery and what kind of recovery is performed.
28502848
/// \param IsCorrectedToColon If not null, suggestion of replace '::' -> ':'
@@ -2853,11 +2851,6 @@ class Sema final : public SemaBase {
28532851
/// not '::'.
28542852
/// \param OnlyNamespace If true, only considers namespaces in lookup.
28552853
///
2856-
/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
2857-
/// that it contains an extra parameter \p ScopeLookupResult, which provides
2858-
/// the result of name lookup within the scope of the nested-name-specifier
2859-
/// that was computed at template definition time.
2860-
///
28612854
/// If ErrorRecoveryLookup is true, then this call is used to improve error
28622855
/// recovery. This means that it should not emit diagnostics, it should
28632856
/// just return true on failure. It also means it should only return a valid
@@ -2866,7 +2859,6 @@ class Sema final : public SemaBase {
28662859
/// specifier.
28672860
bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
28682861
bool EnteringContext, CXXScopeSpec &SS,
2869-
NamedDecl *ScopeLookupResult,
28702862
bool ErrorRecoveryLookup,
28712863
bool *IsCorrectedToColon = nullptr,
28722864
bool OnlyNamespace = false);
@@ -8566,11 +8558,12 @@ class Sema final : public SemaBase {
85668558
const TemplateArgumentListInfo *TemplateArgs,
85678559
bool IsDefiniteInstance, const Scope *S);
85688560

8569-
ExprResult ActOnDependentMemberExpr(
8570-
Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OpLoc,
8571-
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
8572-
NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
8573-
const TemplateArgumentListInfo *TemplateArgs);
8561+
ExprResult
8562+
ActOnDependentMemberExpr(Expr *Base, QualType BaseType, bool IsArrow,
8563+
SourceLocation OpLoc, const CXXScopeSpec &SS,
8564+
SourceLocation TemplateKWLoc,
8565+
const DeclarationNameInfo &NameInfo,
8566+
const TemplateArgumentListInfo *TemplateArgs);
85748567

85758568
/// The main callback when the parser finds something like
85768569
/// expression . [nested-name-specifier] identifier
@@ -8626,15 +8619,14 @@ class Sema final : public SemaBase {
86268619
ExprResult BuildMemberReferenceExpr(
86278620
Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
86288621
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
8629-
NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
8622+
const DeclarationNameInfo &NameInfo,
86308623
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
86318624
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
86328625

86338626
ExprResult
86348627
BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc,
86358628
bool IsArrow, const CXXScopeSpec &SS,
8636-
SourceLocation TemplateKWLoc,
8637-
NamedDecl *FirstQualifierInScope, LookupResult &R,
8629+
SourceLocation TemplateKWLoc, LookupResult &R,
86388630
const TemplateArgumentListInfo *TemplateArgs,
86398631
const Scope *S, bool SuppressQualifierCheck = false,
86408632
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
@@ -11122,15 +11114,14 @@ class Sema final : public SemaBase {
1112211114
QualType ObjectType, bool EnteringContext,
1112311115
RequiredTemplateKind RequiredTemplate = SourceLocation(),
1112411116
AssumedTemplateKind *ATK = nullptr,
11125-
bool AllowTypoCorrection = true);
11117+
bool AllowTypoCorrection = true, bool MayBeNNS = false);
1112611118

11127-
TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
11128-
bool hasTemplateKeyword,
11129-
const UnqualifiedId &Name,
11130-
ParsedType ObjectType, bool EnteringContext,
11131-
TemplateTy &Template,
11132-
bool &MemberOfUnknownSpecialization,
11133-
bool Disambiguation = false);
11119+
TemplateNameKind
11120+
isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword,
11121+
const UnqualifiedId &Name, ParsedType ObjectType,
11122+
bool EnteringContext, TemplateTy &Template,
11123+
bool &MemberOfUnknownSpecialization,
11124+
bool Disambiguation = false, bool MayBeNNS = false);
1113411125

1113511126
/// Try to resolve an undeclared template name as a type template.
1113611127
///
@@ -11459,12 +11450,11 @@ class Sema final : public SemaBase {
1145911450
/// For example, given "x.MetaFun::template apply", the scope specifier
1146011451
/// \p SS will be "MetaFun::", \p TemplateKWLoc contains the location
1146111452
/// of the "template" keyword, and "apply" is the \p Name.
11462-
TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS,
11463-
SourceLocation TemplateKWLoc,
11464-
const UnqualifiedId &Name,
11465-
ParsedType ObjectType,
11466-
bool EnteringContext, TemplateTy &Template,
11467-
bool AllowInjectedClassName = false);
11453+
TemplateNameKind
11454+
ActOnTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
11455+
const UnqualifiedId &Name, ParsedType ObjectType,
11456+
bool EnteringContext, TemplateTy &Template,
11457+
bool AllowInjectedClassName = false, bool MayBeNNS = false);
1146811458

1146911459
DeclResult ActOnClassTemplateSpecialization(
1147011460
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,

0 commit comments

Comments
 (0)