Skip to content

Commit 0c6e1ca

Browse files
committed
Revert "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (#84050)"
This reverts commit a8fd0d0.
1 parent 45fc0e6 commit 0c6e1ca

File tree

30 files changed

+224
-765
lines changed

30 files changed

+224
-765
lines changed

clang-tools-extra/clangd/unittests/FindTargetTests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
854854
}
855855
};
856856
)cpp";
857-
EXPECT_DECLS("MemberExpr", "void foo()");
857+
EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");
858858

859859
// Similar to above but base expression involves a function call.
860860
Code = R"cpp(
@@ -872,7 +872,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
872872
}
873873
};
874874
)cpp";
875-
EXPECT_DECLS("MemberExpr", "void foo()");
875+
EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");
876876

877877
// Similar to above but uses a function pointer.
878878
Code = R"cpp(
@@ -891,7 +891,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
891891
}
892892
};
893893
)cpp";
894-
EXPECT_DECLS("MemberExpr", "void foo()");
894+
EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");
895895

896896
// Base expression involves a member access into this.
897897
Code = R"cpp(
@@ -962,7 +962,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
962962
void Foo() { this->[[find]](); }
963963
};
964964
)cpp";
965-
EXPECT_DECLS("MemberExpr", "void find()");
965+
EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");
966966
}
967967

968968
TEST_F(TargetDeclTest, DependentTypes) {

clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ sizeof...($TemplateParameter[[Elements]]);
621621
struct $Class_def[[Foo]] {
622622
int $Field_decl[[Waldo]];
623623
void $Method_def[[bar]]() {
624-
$Class[[Foo]]().$Field[[Waldo]];
624+
$Class[[Foo]]().$Field_dependentName[[Waldo]];
625625
}
626626
template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]]
627627
void $Method_def[[bar1]]() {

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,6 @@ struct HeapArray { // Ok, since destruc
309309

310310
HeapArray(HeapArray &&other) : _data(other._data), size(other.size) { // Ok
311311
other._data = nullptr; // Ok
312-
// CHECK-NOTES: [[@LINE-1]]:5: warning: expected assignment source to be of type 'gsl::owner<>'; got 'std::nullptr_t'
313-
// FIXME: This warning is emitted because an ImplicitCastExpr for the NullToPointer conversion isn't created for dependent types.
314312
other.size = 0;
315313
}
316314

clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,6 @@ template <class T>
260260
struct Template {
261261
Template() = default;
262262
Template(const Template &Other) : Field(Other.Field) {}
263-
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
264-
// CHECK-FIXES: Template(const Template &Other) = default;
265263
Template &operator=(const Template &Other);
266264
void foo(const T &t);
267265
int Field;
@@ -271,12 +269,8 @@ Template<T> &Template<T>::operator=(const Template<T> &Other) {
271269
Field = Other.Field;
272270
return *this;
273271
}
274-
// CHECK-MESSAGES: :[[@LINE-4]]:27: warning: use '= default'
275-
// CHECK-FIXES: Template<T> &Template<T>::operator=(const Template<T> &Other) = default;
276-
277272
Template<int> T1;
278273

279-
280274
// Dependent types.
281275
template <class T>
282276
struct DT1 {
@@ -290,9 +284,6 @@ DT1<T> &DT1<T>::operator=(const DT1<T> &Other) {
290284
Field = Other.Field;
291285
return *this;
292286
}
293-
// CHECK-MESSAGES: :[[@LINE-4]]:17: warning: use '= default'
294-
// CHECK-FIXES: DT1<T> &DT1<T>::operator=(const DT1<T> &Other) = default;
295-
296287
DT1<int> Dt1;
297288

298289
template <class T>
@@ -312,9 +303,6 @@ DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
312303
struct T {
313304
typedef int TT;
314305
};
315-
// CHECK-MESSAGES: :[[@LINE-8]]:17: warning: use '= default'
316-
// CHECK-FIXES: DT2<T> &DT2<T>::operator=(const DT2<T> &Other) = default;
317-
318306
DT2<T> Dt2;
319307

320308
// Default arguments.

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -385,18 +385,6 @@ Improvements to Clang's diagnostics
385385

386386
- Clang now diagnoses requires expressions with explicit object parameters.
387387

388-
- Clang now looks up members of the current instantiation in the template definition context
389-
if the current instantiation has no dependent base classes.
390-
391-
.. code-block:: c++
392-
393-
template<typename T>
394-
struct A {
395-
int f() {
396-
return this->x; // error: no member named 'x' in 'A<T>'
397-
}
398-
};
399-
400388
Improvements to Clang's time-trace
401389
----------------------------------
402390

clang/include/clang/Sema/Lookup.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,7 @@ class LookupResult {
499499
/// Note that while no result was found in the current instantiation,
500500
/// there were dependent base classes that could not be searched.
501501
void setNotFoundInCurrentInstantiation() {
502-
assert((ResultKind == NotFound ||
503-
ResultKind == NotFoundInCurrentInstantiation) &&
504-
Decls.empty());
502+
assert(ResultKind == NotFound && Decls.empty());
505503
ResultKind = NotFoundInCurrentInstantiation;
506504
}
507505

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7472,7 +7472,7 @@ class Sema final : public SemaBase {
74727472
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
74737473
CXXScopeSpec &SS);
74747474
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
7475-
QualType ObjectType, bool AllowBuiltinCreation = false,
7475+
bool AllowBuiltinCreation = false,
74767476
bool EnteringContext = false);
74777477
ObjCProtocolDecl *LookupProtocol(
74787478
IdentifierInfo *II, SourceLocation IdLoc,
@@ -8881,13 +8881,11 @@ class Sema final : public SemaBase {
88818881
/// functions (but no function templates).
88828882
FoundFunctions,
88838883
};
8884-
8885-
bool
8886-
LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
8887-
QualType ObjectType, bool EnteringContext,
8888-
RequiredTemplateKind RequiredTemplate = SourceLocation(),
8889-
AssumedTemplateKind *ATK = nullptr,
8890-
bool AllowTypoCorrection = true);
8884+
bool LookupTemplateName(
8885+
LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType,
8886+
bool EnteringContext, bool &MemberOfUnknownSpecialization,
8887+
RequiredTemplateKind RequiredTemplate = SourceLocation(),
8888+
AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);
88918889

88928890
TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
88938891
bool hasTemplateKeyword,

clang/lib/AST/Expr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments(
103103
}
104104
} else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
105105
if (!ME->isArrow()) {
106-
assert(ME->getBase()->getType()->getAsRecordDecl());
106+
assert(ME->getBase()->getType()->isRecordType());
107107
if (const auto *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
108108
if (!Field->isBitField() && !Field->getType()->isReferenceType()) {
109109
E = ME->getBase();

clang/lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2998,7 +2998,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
29982998
<< TokenName << TagName << getLangOpts().CPlusPlus
29992999
<< FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName);
30003000

3001-
if (Actions.LookupName(R, getCurScope())) {
3001+
if (Actions.LookupParsedName(R, getCurScope(), SS)) {
30023002
for (LookupResult::iterator I = R.begin(), IEnd = R.end();
30033003
I != IEnd; ++I)
30043004
Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,12 @@ struct BuiltinTypeDeclBuilder {
126126

127127
static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
128128
StringRef Name) {
129+
CXXScopeSpec SS;
129130
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
130131
DeclarationNameInfo NameInfo =
131132
DeclarationNameInfo(DeclarationName(&II), SourceLocation());
132133
LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
133-
// AllowBuiltinCreation is false but LookupDirect will create
134-
// the builtin when searching the global scope anyways...
135-
S.LookupName(R, S.getCurScope());
136-
// FIXME: If the builtin function was user-declared in global scope,
137-
// this assert *will* fail. Should this call LookupBuiltin instead?
134+
S.LookupParsedName(R, S.getCurScope(), &SS, false);
138135
assert(R.isSingleResult() &&
139136
"Since this is a builtin it should always resolve!");
140137
auto *VD = cast<ValueDecl>(R.getFoundDecl());

clang/lib/Sema/SemaAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
837837

838838
IdentifierInfo *Name = IdTok.getIdentifierInfo();
839839
LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
840-
LookupName(Lookup, curScope, /*AllowBuiltinCreation=*/true);
840+
LookupParsedName(Lookup, curScope, nullptr, true);
841841

842842
if (Lookup.empty()) {
843843
Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)

clang/lib/Sema/SemaDecl.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
832832
IdentifierInfo *&Name,
833833
SourceLocation NameLoc) {
834834
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName);
835-
SemaRef.LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
835+
SemaRef.LookupParsedName(R, S, &SS);
836836
if (TagDecl *Tag = R.getAsSingle<TagDecl>()) {
837837
StringRef FixItTagName;
838838
switch (Tag->getTagKind()) {
@@ -869,7 +869,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
869869

870870
// Replace lookup results with just the tag decl.
871871
Result.clear(Sema::LookupTagName);
872-
SemaRef.LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType());
872+
SemaRef.LookupParsedName(Result, S, &SS);
873873
return true;
874874
}
875875

@@ -896,8 +896,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
896896
}
897897

898898
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
899-
LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType(),
900-
/*AllowBuiltinCreation=*/!CurMethod);
899+
LookupParsedName(Result, S, &SS, !CurMethod);
901900

902901
if (SS.isInvalid())
903902
return NameClassification::Error();

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4517,7 +4517,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
45174517
DS.getBeginLoc(), DS.getEllipsisLoc());
45184518
} else {
45194519
LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
4520-
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
4520+
LookupParsedName(R, S, &SS);
45214521

45224522
TypeDecl *TyD = R.getAsSingle<TypeDecl>();
45234523
if (!TyD) {
@@ -12262,7 +12262,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
1226212262

1226312263
// Lookup namespace name.
1226412264
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
12265-
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
12265+
LookupParsedName(R, S, &SS);
1226612266
if (R.isAmbiguous())
1226712267
return nullptr;
1226812268

@@ -13721,7 +13721,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
1372113721

1372213722
// Lookup the namespace name.
1372313723
LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
13724-
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
13724+
LookupParsedName(R, S, &SS);
1372513725

1372613726
if (R.isAmbiguous())
1372713727
return nullptr;

clang/lib/Sema/SemaExpr.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
673673
// expressions of certain types in C++.
674674
if (getLangOpts().CPlusPlus &&
675675
(E->getType() == Context.OverloadTy ||
676-
// FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied
677-
// to pointer types even if the pointee type is dependent.
678-
(T->isDependentType() && !T->isPointerType()) || T->isRecordType()))
676+
T->isDependentType() ||
677+
T->isRecordType()))
679678
return E;
680679

681680
// The C standard is actually really unclear on this point, and
@@ -2752,8 +2751,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
27522751
if (isBoundsAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
27532752
// See if this is reference to a field of struct.
27542753
LookupResult R(*this, NameInfo, LookupMemberName);
2755-
// LookupName handles a name lookup from within anonymous struct.
2756-
if (LookupName(R, S)) {
2754+
// LookupParsedName handles a name lookup from within anonymous struct.
2755+
if (LookupParsedName(R, S, &SS)) {
27572756
if (auto *VD = dyn_cast<ValueDecl>(R.getFoundDecl())) {
27582757
QualType type = VD->getType().getNonReferenceType();
27592758
// This will eventually be translated into MemberExpr upon
@@ -2774,19 +2773,20 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
27742773
// lookup to determine that it was a template name in the first place. If
27752774
// this becomes a performance hit, we can work harder to preserve those
27762775
// results until we get here but it's likely not worth it.
2776+
bool MemberOfUnknownSpecialization;
27772777
AssumedTemplateKind AssumedTemplate;
2778-
if (LookupTemplateName(R, S, SS, /*ObjectType=*/QualType(),
2779-
/*EnteringContext=*/false, TemplateKWLoc,
2778+
if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
2779+
MemberOfUnknownSpecialization, TemplateKWLoc,
27802780
&AssumedTemplate))
27812781
return ExprError();
27822782

2783-
if (R.wasNotFoundInCurrentInstantiation())
2783+
if (MemberOfUnknownSpecialization ||
2784+
(R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
27842785
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
27852786
IsAddressOfOperand, TemplateArgs);
27862787
} else {
27872788
bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl();
2788-
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType(),
2789-
/*AllowBuiltinCreation=*/!IvarLookupFollowUp);
2789+
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
27902790

27912791
// If the result might be in a dependent base class, this is a dependent
27922792
// id-expression.

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9157,7 +9157,7 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
91579157
// Do the redeclaration lookup in the current scope.
91589158
LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName,
91599159
RedeclarationKind::NotForRedeclaration);
9160-
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
9160+
LookupParsedName(R, S, &SS);
91619161
R.suppressDiagnostics();
91629162

91639163
switch (R.getResultKind()) {

0 commit comments

Comments
 (0)