Skip to content

Commit af5e149

Browse files
sdkrystianronlieb
authored andcommitted
Reapply "[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 (llvm#84050)" (llvm#90152)
Reapplies llvm#84050, addressing a bug which cases a crash when an expression with the type of the current instantiation is used as the _postfix-expression_ in a class member access expression (arrow form). Change-Id: I17501886f0d2fc833749b4804f339bacbb85753c
1 parent 64fe0df commit af5e149

File tree

29 files changed

+294
-259
lines changed

29 files changed

+294
-259
lines changed

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

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

858858
// Similar to above but base expression involves a function call.
859859
Code = R"cpp(
@@ -871,7 +871,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
871871
}
872872
};
873873
)cpp";
874-
EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");
874+
EXPECT_DECLS("MemberExpr", "void foo()");
875875

876876
// Similar to above but uses a function pointer.
877877
Code = R"cpp(
@@ -890,7 +890,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
890890
}
891891
};
892892
)cpp";
893-
EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");
893+
EXPECT_DECLS("MemberExpr", "void foo()");
894894

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

967967
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_dependentName[[Waldo]];
624+
$Class[[Foo]]().$Field[[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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ 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.
312314
other.size = 0;
313315
}
314316

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ 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;
263265
Template &operator=(const Template &Other);
264266
void foo(const T &t);
265267
int Field;
@@ -269,8 +271,12 @@ Template<T> &Template<T>::operator=(const Template<T> &Other) {
269271
Field = Other.Field;
270272
return *this;
271273
}
274+
// CHECK-MESSAGES: :[[@LINE-4]]:27: warning: use '= default'
275+
// CHECK-FIXES: Template<T> &Template<T>::operator=(const Template<T> &Other) = default;
276+
272277
Template<int> T1;
273278

279+
274280
// Dependent types.
275281
template <class T>
276282
struct DT1 {
@@ -284,6 +290,9 @@ DT1<T> &DT1<T>::operator=(const DT1<T> &Other) {
284290
Field = Other.Field;
285291
return *this;
286292
}
293+
// CHECK-MESSAGES: :[[@LINE-4]]:17: warning: use '= default'
294+
// CHECK-FIXES: DT1<T> &DT1<T>::operator=(const DT1<T> &Other) = default;
295+
287296
DT1<int> Dt1;
288297

289298
template <class T>
@@ -303,6 +312,9 @@ DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
303312
struct T {
304313
typedef int TT;
305314
};
315+
// CHECK-MESSAGES: :[[@LINE-8]]:17: warning: use '= default'
316+
// CHECK-FIXES: DT2<T> &DT2<T>::operator=(const DT2<T> &Other) = default;
317+
306318
DT2<T> Dt2;
307319

308320
// Default arguments.

clang/include/clang/Sema/Lookup.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,9 @@ 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 && Decls.empty());
502+
assert((ResultKind == NotFound ||
503+
ResultKind == NotFoundInCurrentInstantiation) &&
504+
Decls.empty());
503505
ResultKind = NotFoundInCurrentInstantiation;
504506
}
505507

clang/include/clang/Sema/Sema.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8589,12 +8589,6 @@ class Sema final : public SemaBase {
85898589
SourceLocation TemplateKWLoc,
85908590
UnqualifiedId &Member, Decl *ObjCImpDecl);
85918591

8592-
MemberExpr *BuildMemberExpr(
8593-
Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS,
8594-
SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
8595-
bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
8596-
QualType Ty, ExprValueKind VK, ExprObjectKind OK,
8597-
const TemplateArgumentListInfo *TemplateArgs = nullptr);
85988592
MemberExpr *
85998593
BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
86008594
NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
@@ -9191,7 +9185,7 @@ class Sema final : public SemaBase {
91919185
///
91929186
/// @returns True if any decls were found (but possibly ambiguous)
91939187
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
9194-
bool AllowBuiltinCreation = false,
9188+
QualType ObjectType, bool AllowBuiltinCreation = false,
91959189
bool EnteringContext = false);
91969190

91979191
/// Perform qualified name lookup into all base classes of the given
@@ -11124,11 +11118,13 @@ class Sema final : public SemaBase {
1112411118
/// functions (but no function templates).
1112511119
FoundFunctions,
1112611120
};
11127-
bool LookupTemplateName(
11128-
LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType,
11129-
bool EnteringContext, bool &MemberOfUnknownSpecialization,
11130-
RequiredTemplateKind RequiredTemplate = SourceLocation(),
11131-
AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);
11121+
11122+
bool
11123+
LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
11124+
QualType ObjectType, bool EnteringContext,
11125+
RequiredTemplateKind RequiredTemplate = SourceLocation(),
11126+
AssumedTemplateKind *ATK = nullptr,
11127+
bool AllowTypoCorrection = true);
1113211128

1113311129
TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
1113411130
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()->isRecordType());
106+
assert(ME->getBase()->getType()->getAsRecordDecl());
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
@@ -3097,7 +3097,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
30973097
<< TokenName << TagName << getLangOpts().CPlusPlus
30983098
<< FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName);
30993099

3100-
if (Actions.LookupParsedName(R, getCurScope(), SS)) {
3100+
if (Actions.LookupName(R, getCurScope())) {
31013101
for (LookupResult::iterator I = R.begin(), IEnd = R.end();
31023102
I != IEnd; ++I)
31033103
Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)

clang/lib/Sema/HLSLExternalSemaSource.cpp

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

127127
static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
128128
StringRef Name) {
129-
CXXScopeSpec SS;
130129
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
131130
DeclarationNameInfo NameInfo =
132131
DeclarationNameInfo(DeclarationName(&II), SourceLocation());
133132
LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
134-
S.LookupParsedName(R, S.getCurScope(), &SS, false);
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?
135138
assert(R.isSingleResult() &&
136139
"Since this is a builtin it should always resolve!");
137140
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-
LookupParsedName(Lookup, curScope, nullptr, true);
840+
LookupName(Lookup, curScope, /*AllowBuiltinCreation=*/true);
841841

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

clang/lib/Sema/SemaDecl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
811811
IdentifierInfo *&Name,
812812
SourceLocation NameLoc) {
813813
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName);
814-
SemaRef.LookupParsedName(R, S, &SS);
814+
SemaRef.LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
815815
if (TagDecl *Tag = R.getAsSingle<TagDecl>()) {
816816
StringRef FixItTagName;
817817
switch (Tag->getTagKind()) {
@@ -848,7 +848,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
848848

849849
// Replace lookup results with just the tag decl.
850850
Result.clear(Sema::LookupTagName);
851-
SemaRef.LookupParsedName(Result, S, &SS);
851+
SemaRef.LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType());
852852
return true;
853853
}
854854

@@ -875,7 +875,8 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
875875
}
876876

877877
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
878-
LookupParsedName(Result, S, &SS, !CurMethod);
878+
LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType(),
879+
/*AllowBuiltinCreation=*/!CurMethod);
879880

880881
if (SS.isInvalid())
881882
return NameClassification::Error();

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4437,7 +4437,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
44374437
DS.getBeginLoc(), DS.getEllipsisLoc());
44384438
} else {
44394439
LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
4440-
LookupParsedName(R, S, &SS);
4440+
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
44414441

44424442
TypeDecl *TyD = R.getAsSingle<TypeDecl>();
44434443
if (!TyD) {
@@ -12140,7 +12140,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
1214012140

1214112141
// Lookup namespace name.
1214212142
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
12143-
LookupParsedName(R, S, &SS);
12143+
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
1214412144
if (R.isAmbiguous())
1214512145
return nullptr;
1214612146

@@ -13551,7 +13551,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
1355113551

1355213552
// Lookup the namespace name.
1355313553
LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
13554-
LookupParsedName(R, S, &SS);
13554+
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
1355513555

1355613556
if (R.isAmbiguous())
1355713557
return nullptr;

clang/lib/Sema/SemaExpr.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
655655

656656
// We don't want to throw lvalue-to-rvalue casts on top of
657657
// expressions of certain types in C++.
658+
658659
if (getLangOpts().CPlusPlus) {
659660
if (T == Context.OverloadTy || T->isRecordType() ||
660661
(T->isDependentType() && !T->isAnyPointerType() &&
@@ -2700,8 +2701,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
27002701
if (isAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
27012702
// See if this is reference to a field of struct.
27022703
LookupResult R(*this, NameInfo, LookupMemberName);
2703-
// LookupParsedName handles a name lookup from within anonymous struct.
2704-
if (LookupParsedName(R, S, &SS)) {
2704+
// LookupName handles a name lookup from within anonymous struct.
2705+
if (LookupName(R, S)) {
27052706
if (auto *VD = dyn_cast<ValueDecl>(R.getFoundDecl())) {
27062707
QualType type = VD->getType().getNonReferenceType();
27072708
// This will eventually be translated into MemberExpr upon
@@ -2722,10 +2723,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
27222723
// lookup to determine that it was a template name in the first place. If
27232724
// this becomes a performance hit, we can work harder to preserve those
27242725
// results until we get here but it's likely not worth it.
2725-
bool MemberOfUnknownSpecialization;
27262726
AssumedTemplateKind AssumedTemplate;
2727-
if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
2728-
MemberOfUnknownSpecialization, TemplateKWLoc,
2727+
if (LookupTemplateName(R, S, SS, /*ObjectType=*/QualType(),
2728+
/*EnteringContext=*/false, TemplateKWLoc,
27292729
&AssumedTemplate))
27302730
return ExprError();
27312731

@@ -2734,7 +2734,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
27342734
IsAddressOfOperand, TemplateArgs);
27352735
} else {
27362736
bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl();
2737-
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
2737+
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType(),
2738+
/*AllowBuiltinCreation=*/!IvarLookupFollowUp);
27382739

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

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9096,7 +9096,7 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
90969096
// Do the redeclaration lookup in the current scope.
90979097
LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName,
90989098
RedeclarationKind::NotForRedeclaration);
9099-
LookupParsedName(R, S, &SS);
9099+
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
91009100
R.suppressDiagnostics();
91019101

91029102
switch (R.getResultKind()) {

0 commit comments

Comments
 (0)