Skip to content

Commit 59e56ee

Browse files
committed
Revert "Reapply "[Clang] Implement resolution for CWG1835 (#92957)" (#98547)"
This reverts commit ce4aada and a follow-up patch 8ef26f1. This new warning can not be fully suppressed by the `-Wno-missing-dependent-template-keyword` flag, this gives developer no time to do the cleanup in a large codebase, see #98547 (comment)
1 parent 6484655 commit 59e56ee

Some content is hidden

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

47 files changed

+815
-1121
lines changed

clang/docs/ReleaseNotes.rst

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

316-
- Clang now correctly implements lookup for the terminal name of a member-qualified nested-name-specifier.
317-
(`CWG1835: Dependent member lookup before < <https://cplusplus.github.io/CWG/issues/1835.html>`_).
318-
The warning can be disabled via `-Wno-missing-dependent-template-keyword`.
319-
320316
C Language Changes
321317
------------------
322318

clang/include/clang/AST/ExprCXX.h

Lines changed: 43 additions & 49 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<
3680-
CXXDependentScopeMemberExpr, NestedNameSpecifierLoc, DeclAccessPair,
3681-
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
3679+
private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
3680+
ASTTemplateKWAndArgsInfo,
3681+
TemplateArgumentLoc, NamedDecl *> {
36823682
friend class ASTStmtReader;
36833683
friend class ASTStmtWriter;
36843684
friend TrailingObjects;
@@ -3691,15 +3691,17 @@ 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+
36943699
/// The member to which this member expression refers, which
36953700
/// can be name, overloaded operator, or destructor.
36963701
///
36973702
/// FIXME: could also be a template-id
36983703
DeclarationNameInfo MemberNameInfo;
36993704

3700-
/// The location of the '->' or '.' operator.
3701-
SourceLocation OperatorLoc;
3702-
37033705
// CXXDependentScopeMemberExpr is followed by several trailing objects,
37043706
// some of which optional. They are in order:
37053707
//
@@ -3719,16 +3721,8 @@ class CXXDependentScopeMemberExpr final
37193721
return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo;
37203722
}
37213723

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();
3724+
bool hasFirstQualifierFoundInScope() const {
3725+
return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope;
37323726
}
37333727

37343728
unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
@@ -3739,32 +3733,33 @@ class CXXDependentScopeMemberExpr final
37393733
return getNumTemplateArgs();
37403734
}
37413735

3736+
unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const {
3737+
return hasFirstQualifierFoundInScope();
3738+
}
3739+
37423740
CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base,
37433741
QualType BaseType, bool IsArrow,
37443742
SourceLocation OperatorLoc,
37453743
NestedNameSpecifierLoc QualifierLoc,
37463744
SourceLocation TemplateKWLoc,
3747-
ArrayRef<DeclAccessPair> UnqualifiedLookups,
3745+
NamedDecl *FirstQualifierFoundInScope,
37483746
DeclarationNameInfo MemberNameInfo,
37493747
const TemplateArgumentListInfo *TemplateArgs);
37503748

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

37553752
public:
37563753
static CXXDependentScopeMemberExpr *
37573754
Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
37583755
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
3759-
SourceLocation TemplateKWLoc,
3760-
ArrayRef<DeclAccessPair> UnqualifiedLookups,
3756+
SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
37613757
DeclarationNameInfo MemberNameInfo,
37623758
const TemplateArgumentListInfo *TemplateArgs);
37633759

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

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

37913786
/// Retrieve the location of the '->' or '.' operator.
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;
3798-
}
3799-
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>();
3787+
SourceLocation getOperatorLoc() const {
3788+
return CXXDependentScopeMemberExprBits.OperatorLoc;
38063789
}
38073790

3808-
/// If the member name was qualified, retrieves the
3809-
/// nested-name-specifier that precedes the member name. Otherwise, returns
3810-
/// NULL.
3791+
/// Retrieve the nested-name-specifier that qualifies the member name.
38113792
NestedNameSpecifier *getQualifier() const {
3812-
return getQualifierLoc().getNestedNameSpecifier();
3793+
return QualifierLoc.getNestedNameSpecifier();
38133794
}
38143795

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()};
3796+
/// Retrieve the nested-name-specifier that qualifies the member
3797+
/// name, with source location information.
3798+
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
3799+
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 *>();
38213815
}
38223816

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

clang/include/clang/AST/Stmt.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,19 +1020,18 @@ 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-
10281023
/// Whether this member expression has info for explicit template
10291024
/// keyword and arguments.
10301025
LLVM_PREFERRED_TYPE(bool)
10311026
unsigned HasTemplateKWAndArgsInfo : 1;
10321027

1033-
/// Number of declarations found by unqualified lookup for the
1034-
/// first component name of the nested-name-specifier.
1035-
unsigned NumUnqualifiedLookups;
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;
10361035
};
10371036

10381037
class OverloadExprBitfields {

clang/include/clang/AST/UnresolvedSet.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,6 @@ 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-
104100
/// Replaces the given declaration with the new one, once.
105101
///
106102
/// \return true if the set changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -895,9 +895,10 @@ 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 ext_missing_dependent_template_keyword : ExtWarn<
899-
"use 'template' keyword to treat '%0' as a dependent template name">,
900-
InGroup<DiagGroup<"missing-dependent-template-keyword">>;
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<
901+
"use 'template' keyword to treat '%0' as a dependent template name">;
901902

902903
def ext_extern_template : Extension<
903904
"extern templates are a C++11 extension">, InGroup<CXX11>;

clang/include/clang/Parse/Parser.h

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

3375-
bool ParseUnqualifiedIdTemplateId(
3376-
CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
3377-
SourceLocation TemplateKWLoc, SourceLocation TildeLoc,
3378-
IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext,
3379-
UnqualifiedId &Id, bool AssumeTemplateId);
3375+
bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
3376+
ParsedType ObjectType,
3377+
bool ObjectHadErrors,
3378+
SourceLocation TemplateKWLoc,
3379+
IdentifierInfo *Name,
3380+
SourceLocation NameLoc,
3381+
bool EnteringContext,
3382+
UnqualifiedId &Id,
3383+
bool AssumeTemplateId);
33803384
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
33813385
ParsedType ObjectType,
33823386
UnqualifiedId &Result);

clang/include/clang/Sema/DeclSpec.h

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

8079
public:
8180
SourceRange getRange() const { return Range; }
@@ -92,13 +91,6 @@ class CXXScopeSpec {
9291
return TemplateParamLists;
9392
}
9493

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

clang/include/clang/Sema/Lookup.h

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

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

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

clang/include/clang/Sema/Sema.h

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

28092808
/// Keeps information about an identifier in a nested-name-spec.
28102809
///
@@ -2844,6 +2843,9 @@ class Sema final : public SemaBase {
28442843
/// \param EnteringContext If true, enter the context specified by the
28452844
/// nested-name-specifier.
28462845
/// \param SS Optional nested name specifier preceding the identifier.
2846+
/// \param ScopeLookupResult Provides the result of name lookup within the
2847+
/// scope of the nested-name-specifier that was computed at template
2848+
/// definition time.
28472849
/// \param ErrorRecoveryLookup Specifies if the method is called to improve
28482850
/// error recovery and what kind of recovery is performed.
28492851
/// \param IsCorrectedToColon If not null, suggestion of replace '::' -> ':'
@@ -2852,6 +2854,11 @@ class Sema final : public SemaBase {
28522854
/// not '::'.
28532855
/// \param OnlyNamespace If true, only considers namespaces in lookup.
28542856
///
2857+
/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in
2858+
/// that it contains an extra parameter \p ScopeLookupResult, which provides
2859+
/// the result of name lookup within the scope of the nested-name-specifier
2860+
/// that was computed at template definition time.
2861+
///
28552862
/// If ErrorRecoveryLookup is true, then this call is used to improve error
28562863
/// recovery. This means that it should not emit diagnostics, it should
28572864
/// just return true on failure. It also means it should only return a valid
@@ -2860,6 +2867,7 @@ class Sema final : public SemaBase {
28602867
/// specifier.
28612868
bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
28622869
bool EnteringContext, CXXScopeSpec &SS,
2870+
NamedDecl *ScopeLookupResult,
28632871
bool ErrorRecoveryLookup,
28642872
bool *IsCorrectedToColon = nullptr,
28652873
bool OnlyNamespace = false);
@@ -8559,12 +8567,11 @@ class Sema final : public SemaBase {
85598567
const TemplateArgumentListInfo *TemplateArgs,
85608568
bool IsDefiniteInstance, const Scope *S);
85618569

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

85698576
/// The main callback when the parser finds something like
85708577
/// expression . [nested-name-specifier] identifier
@@ -8620,14 +8627,15 @@ class Sema final : public SemaBase {
86208627
ExprResult BuildMemberReferenceExpr(
86218628
Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
86228629
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
8623-
const DeclarationNameInfo &NameInfo,
8630+
NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
86248631
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
86258632
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
86268633

86278634
ExprResult
86288635
BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc,
86298636
bool IsArrow, const CXXScopeSpec &SS,
8630-
SourceLocation TemplateKWLoc, LookupResult &R,
8637+
SourceLocation TemplateKWLoc,
8638+
NamedDecl *FirstQualifierInScope, LookupResult &R,
86318639
const TemplateArgumentListInfo *TemplateArgs,
86328640
const Scope *S, bool SuppressQualifierCheck = false,
86338641
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
@@ -11115,14 +11123,15 @@ class Sema final : public SemaBase {
1111511123
QualType ObjectType, bool EnteringContext,
1111611124
RequiredTemplateKind RequiredTemplate = SourceLocation(),
1111711125
AssumedTemplateKind *ATK = nullptr,
11118-
bool AllowTypoCorrection = true, bool MayBeNNS = false);
11126+
bool AllowTypoCorrection = true);
1111911127

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

1112711136
/// Try to resolve an undeclared template name as a type template.
1112811137
///
@@ -11455,11 +11464,12 @@ class Sema final : public SemaBase {
1145511464
/// For example, given "x.MetaFun::template apply", the scope specifier
1145611465
/// \p SS will be "MetaFun::", \p TemplateKWLoc contains the location
1145711466
/// of the "template" keyword, and "apply" is the \p Name.
11458-
TemplateNameKind
11459-
ActOnTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
11460-
const UnqualifiedId &Name, ParsedType ObjectType,
11461-
bool EnteringContext, TemplateTy &Template,
11462-
bool AllowInjectedClassName = false, bool MayBeNNS = false);
11467+
TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS,
11468+
SourceLocation TemplateKWLoc,
11469+
const UnqualifiedId &Name,
11470+
ParsedType ObjectType,
11471+
bool EnteringContext, TemplateTy &Template,
11472+
bool AllowInjectedClassName = false);
1146311473

1146411474
DeclResult ActOnClassTemplateSpecialization(
1146511475
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,

0 commit comments

Comments
 (0)