-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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 (#84050)" #90152
Conversation
@llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy Author: Krystian Stasiowski (sdkrystian) ChangesReapplies #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). Patch is 68.66 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/90152.diff 30 Files Affected:
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 799a549ff0816e..94437857cecca6 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -854,7 +854,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
}
};
)cpp";
- EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");
+ EXPECT_DECLS("MemberExpr", "void foo()");
// Similar to above but base expression involves a function call.
Code = R"cpp(
@@ -872,7 +872,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
}
};
)cpp";
- EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");
+ EXPECT_DECLS("MemberExpr", "void foo()");
// Similar to above but uses a function pointer.
Code = R"cpp(
@@ -891,7 +891,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
}
};
)cpp";
- EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");
+ EXPECT_DECLS("MemberExpr", "void foo()");
// Base expression involves a member access into this.
Code = R"cpp(
@@ -962,7 +962,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
void Foo() { this->[[find]](); }
};
)cpp";
- EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");
+ EXPECT_DECLS("MemberExpr", "void find()");
}
TEST_F(TargetDeclTest, DependentTypes) {
diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
index 4156921d83edf8..30b9b1902aa9c7 100644
--- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -621,7 +621,7 @@ sizeof...($TemplateParameter[[Elements]]);
struct $Class_def[[Foo]] {
int $Field_decl[[Waldo]];
void $Method_def[[bar]]() {
- $Class[[Foo]]().$Field_dependentName[[Waldo]];
+ $Class[[Foo]]().$Field[[Waldo]];
}
template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]]
void $Method_def[[bar1]]() {
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp
index 574efe7bd91478..ae61b17ca14d20 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp
@@ -309,6 +309,8 @@ struct HeapArray { // Ok, since destruc
HeapArray(HeapArray &&other) : _data(other._data), size(other.size) { // Ok
other._data = nullptr; // Ok
+ // CHECK-NOTES: [[@LINE-1]]:5: warning: expected assignment source to be of type 'gsl::owner<>'; got 'std::nullptr_t'
+ // FIXME: This warning is emitted because an ImplicitCastExpr for the NullToPointer conversion isn't created for dependent types.
other.size = 0;
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp
index 559031cf4d9bda..4abb9c8555970e 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp
@@ -260,6 +260,8 @@ template <class T>
struct Template {
Template() = default;
Template(const Template &Other) : Field(Other.Field) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: Template(const Template &Other) = default;
Template &operator=(const Template &Other);
void foo(const T &t);
int Field;
@@ -269,8 +271,12 @@ Template<T> &Template<T>::operator=(const Template<T> &Other) {
Field = Other.Field;
return *this;
}
+// CHECK-MESSAGES: :[[@LINE-4]]:27: warning: use '= default'
+// CHECK-FIXES: Template<T> &Template<T>::operator=(const Template<T> &Other) = default;
+
Template<int> T1;
+
// Dependent types.
template <class T>
struct DT1 {
@@ -284,6 +290,9 @@ DT1<T> &DT1<T>::operator=(const DT1<T> &Other) {
Field = Other.Field;
return *this;
}
+// CHECK-MESSAGES: :[[@LINE-4]]:17: warning: use '= default'
+// CHECK-FIXES: DT1<T> &DT1<T>::operator=(const DT1<T> &Other) = default;
+
DT1<int> Dt1;
template <class T>
@@ -303,6 +312,9 @@ DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
struct T {
typedef int TT;
};
+// CHECK-MESSAGES: :[[@LINE-8]]:17: warning: use '= default'
+// CHECK-FIXES: DT2<T> &DT2<T>::operator=(const DT2<T> &Other) = default;
+
DT2<T> Dt2;
// Default arguments.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f5e5d3a2e6ea36..00c684e773a2e0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -385,6 +385,18 @@ Improvements to Clang's diagnostics
- Clang now diagnoses requires expressions with explicit object parameters.
+- Clang now looks up members of the current instantiation in the template definition context
+ if the current instantiation has no dependent base classes.
+
+ .. code-block:: c++
+
+ template<typename T>
+ struct A {
+ int f() {
+ return this->x; // error: no member named 'x' in 'A<T>'
+ }
+ };
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h
index 0db5b847038ffd..b0a08a05ac6a0a 100644
--- a/clang/include/clang/Sema/Lookup.h
+++ b/clang/include/clang/Sema/Lookup.h
@@ -499,7 +499,9 @@ class LookupResult {
/// Note that while no result was found in the current instantiation,
/// there were dependent base classes that could not be searched.
void setNotFoundInCurrentInstantiation() {
- assert(ResultKind == NotFound && Decls.empty());
+ assert((ResultKind == NotFound ||
+ ResultKind == NotFoundInCurrentInstantiation) &&
+ Decls.empty());
ResultKind = NotFoundInCurrentInstantiation;
}
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1ca523ec88c2f9..aa182b15e66ecc 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7472,7 +7472,7 @@ class Sema final : public SemaBase {
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
CXXScopeSpec &SS);
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
- bool AllowBuiltinCreation = false,
+ QualType ObjectType, bool AllowBuiltinCreation = false,
bool EnteringContext = false);
ObjCProtocolDecl *LookupProtocol(
IdentifierInfo *II, SourceLocation IdLoc,
@@ -8881,11 +8881,13 @@ class Sema final : public SemaBase {
/// functions (but no function templates).
FoundFunctions,
};
- bool LookupTemplateName(
- LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType,
- bool EnteringContext, bool &MemberOfUnknownSpecialization,
- RequiredTemplateKind RequiredTemplate = SourceLocation(),
- AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);
+
+ bool
+ LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
+ QualType ObjectType, bool EnteringContext,
+ RequiredTemplateKind RequiredTemplate = SourceLocation(),
+ AssumedTemplateKind *ATK = nullptr,
+ bool AllowTypoCorrection = true);
TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
bool hasTemplateKeyword,
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 63dcdb919c7117..d2e40be59d6f3b 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -103,7 +103,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments(
}
} else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
if (!ME->isArrow()) {
- assert(ME->getBase()->getType()->isRecordType());
+ assert(ME->getBase()->getType()->getAsRecordDecl());
if (const auto *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
if (!Field->isBitField() && !Field->getType()->isReferenceType()) {
E = ME->getBase();
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 05ad5ecbfaa0cf..53a33fa4add54e 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2998,7 +2998,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
<< TokenName << TagName << getLangOpts().CPlusPlus
<< FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName);
- if (Actions.LookupParsedName(R, getCurScope(), SS)) {
+ if (Actions.LookupName(R, getCurScope())) {
for (LookupResult::iterator I = R.begin(), IEnd = R.end();
I != IEnd; ++I)
Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 1a1febf7a35241..bb283c54b3d29c 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -126,12 +126,15 @@ struct BuiltinTypeDeclBuilder {
static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
StringRef Name) {
- CXXScopeSpec SS;
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
DeclarationNameInfo NameInfo =
DeclarationNameInfo(DeclarationName(&II), SourceLocation());
LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
- S.LookupParsedName(R, S.getCurScope(), &SS, false);
+ // AllowBuiltinCreation is false but LookupDirect will create
+ // the builtin when searching the global scope anyways...
+ S.LookupName(R, S.getCurScope());
+ // FIXME: If the builtin function was user-declared in global scope,
+ // this assert *will* fail. Should this call LookupBuiltin instead?
assert(R.isSingleResult() &&
"Since this is a builtin it should always resolve!");
auto *VD = cast<ValueDecl>(R.getFoundDecl());
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index a5dd158808f26b..a83b1e8afadbc6 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -837,7 +837,7 @@ void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
IdentifierInfo *Name = IdTok.getIdentifierInfo();
LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
- LookupParsedName(Lookup, curScope, nullptr, true);
+ LookupName(Lookup, curScope, /*AllowBuiltinCreation=*/true);
if (Lookup.empty()) {
Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e0745fe9a45367..4e275dc15fbb4e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -832,7 +832,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
IdentifierInfo *&Name,
SourceLocation NameLoc) {
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName);
- SemaRef.LookupParsedName(R, S, &SS);
+ SemaRef.LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
if (TagDecl *Tag = R.getAsSingle<TagDecl>()) {
StringRef FixItTagName;
switch (Tag->getTagKind()) {
@@ -869,7 +869,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
// Replace lookup results with just the tag decl.
Result.clear(Sema::LookupTagName);
- SemaRef.LookupParsedName(Result, S, &SS);
+ SemaRef.LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType());
return true;
}
@@ -896,7 +896,8 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
}
LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
- LookupParsedName(Result, S, &SS, !CurMethod);
+ LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType(),
+ /*AllowBuiltinCreation=*/!CurMethod);
if (SS.isInvalid())
return NameClassification::Error();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index abdbc9d8830c03..4d5836720a651f 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4517,7 +4517,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
DS.getBeginLoc(), DS.getEllipsisLoc());
} else {
LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
- LookupParsedName(R, S, &SS);
+ LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
TypeDecl *TyD = R.getAsSingle<TypeDecl>();
if (!TyD) {
@@ -12262,7 +12262,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
- LookupParsedName(R, S, &SS);
+ LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
if (R.isAmbiguous())
return nullptr;
@@ -13721,7 +13721,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
// Lookup the namespace name.
LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
- LookupParsedName(R, S, &SS);
+ LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
if (R.isAmbiguous())
return nullptr;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 50f92c496a539a..0c37f43f75401b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -673,8 +673,9 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// expressions of certain types in C++.
if (getLangOpts().CPlusPlus &&
(E->getType() == Context.OverloadTy ||
- T->isDependentType() ||
- T->isRecordType()))
+ // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied
+ // to pointer types even if the pointee type is dependent.
+ (T->isDependentType() && !T->isPointerType()) || T->isRecordType()))
return E;
// The C standard is actually really unclear on this point, and
@@ -2751,8 +2752,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
if (isBoundsAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
// See if this is reference to a field of struct.
LookupResult R(*this, NameInfo, LookupMemberName);
- // LookupParsedName handles a name lookup from within anonymous struct.
- if (LookupParsedName(R, S, &SS)) {
+ // LookupName handles a name lookup from within anonymous struct.
+ if (LookupName(R, S)) {
if (auto *VD = dyn_cast<ValueDecl>(R.getFoundDecl())) {
QualType type = VD->getType().getNonReferenceType();
// This will eventually be translated into MemberExpr upon
@@ -2773,20 +2774,19 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// lookup to determine that it was a template name in the first place. If
// this becomes a performance hit, we can work harder to preserve those
// results until we get here but it's likely not worth it.
- bool MemberOfUnknownSpecialization;
AssumedTemplateKind AssumedTemplate;
- if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
- MemberOfUnknownSpecialization, TemplateKWLoc,
+ if (LookupTemplateName(R, S, SS, /*ObjectType=*/QualType(),
+ /*EnteringContext=*/false, TemplateKWLoc,
&AssumedTemplate))
return ExprError();
- if (MemberOfUnknownSpecialization ||
- (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
+ if (R.wasNotFoundInCurrentInstantiation())
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
IsAddressOfOperand, TemplateArgs);
} else {
bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl();
- LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
+ LookupParsedName(R, S, &SS, /*ObjectType=*/QualType(),
+ /*AllowBuiltinCreation=*/!IvarLookupFollowUp);
// If the result might be in a dependent base class, this is a dependent
// id-expression.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 779a41620033dc..c1cb03e4ec7ae2 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -9157,7 +9157,7 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S,
// Do the redeclaration lookup in the current scope.
LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName,
RedeclarationKind::NotForRedeclaration);
- LookupParsedName(R, S, &SS);
+ LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
R.suppressDiagnostics();
switch (R.getResultKind()) {
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 6e30716b9ae436..87fa2518475d5a 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -667,8 +667,8 @@ namespace {
// classes, one of its base classes.
class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
public:
- explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
- : Record(RTy->getDecl()) {
+ explicit RecordMemberExprValidatorCCC(QualType RTy)
+ : Record(RTy->getAsRecordDecl()) {
// Don't add bare keywords to the consumer since they will always fail
// validation by virtue of not being associated with any decls.
WantTypeSpecifiers = false;
@@ -713,58 +713,36 @@ class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
}
static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
- Expr *BaseExpr,
- const RecordType *RTy,
+ Expr *BaseExpr, QualType RTy,
SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS, bool HasTemplateArgs,
SourceLocation TemplateKWLoc,
TypoExpr *&TE) {
SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
- RecordDecl *RDecl = RTy->getDecl();
- if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
- SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
- diag::err_typecheck_incomplete_tag,
- BaseRange))
+ if (!RTy->isDependentType() &&
+ !SemaRef.isThisOutsideMemberFunctionBody(RTy) &&
+ SemaRef.RequireCompleteType(
+ OpLoc, RTy, diag::err_typecheck_incomplete_tag, BaseRange))
return true;
- if (HasTemplateArgs || TemplateKWLoc.isValid()) {
- // LookupTemplateName doesn't expect these both to exist simultaneously.
- QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
+ // LookupTemplateName/LookupParsedName don't expect these both to exist
+ // simultaneously.
+ QualType ObjectType = SS.isSet() ? QualType() : RTy;
+ if (HasTemplateArgs || TemplateKWLoc.isValid())
+ return SemaRef.LookupTemplateName(R,
+ /*S=*/nullptr, SS, ObjectType,
+ /*EnteringContext=*/false, TemplateKWLoc);
- bool MOUS;
- return SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS,
- TemplateKWLoc);
- }
-
- DeclContext *DC = RDecl;
- if (SS.isSet()) {
- // If the member name was a qualified-id, look into the
- // nested-name-specifier.
- DC = SemaRef.computeDeclContext(SS, false);
-
- if (SemaRef.RequireCompleteDeclContext(SS, DC)) {
- SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
- << SS.getRange() << DC;
- return true;
- }
-
- assert(DC && "Cannot handle non-computable dependent contexts in lookup");
-
- if (!isa<TypeDecl>(DC)) {
- SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass)
- << DC << SS.getRange();
- return true;
- }
- }
+ SemaRef.LookupParsedName(R, /*S=*/nullp...
[truncated]
|
Will add tests tomorrow... |
39b5189
to
0ce313a
Compare
da7472e
to
b8fda81
Compare
Please also identify the changes you made vs the previous patch. |
@erichkeane I placed all the new changes into a single commit (unless you mean "reference the changes since the previous patch in the commit message", which I can do). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code changes LGTM, please add the tests, and I'll do another run at this.
Tests have already been added :) @erichkeane (see tests added by b8fda81) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes to Sema.h
and DR tests look good to me.
…g non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (llvm#84050)" Consider the following: ```cpp template<typename T> struct A { auto f() { return this->x; } }; ``` Although `A` has no dependent base classes and the lookup context for `x` is the current instantiation, we currently do not diagnose the absence of a member `x` until `A<T>::f` is instantiated. This patch moves the point of diagnosis for such expressions to occur at the point of definition (i.e. prior to instantiation).
…is the current instantiation
b8fda81
to
8de588d
Compare
@ilya-biryukov I can fix this quickly (less than an hour). |
Awesome, thanks a lot for looking into it! |
@ilya-biryukov See #91972 |
…nstantiation (#91972) #90152 introduced a bug that occurs when typo-correction attempts to fix a reference to a non-existent member of the current instantiation (even though `operator->` may return a different type than the object type). This patch fixes it by simply considering the object expression to be of type `ASTContext::DependentTy` when the arrow operator is used with a dependent non-pointer non-function operand (after any implicit conversions).
@eaeltsin @ilya-biryukov Fixed in 596a9c1 |
Thanks for the quick fix! |
Currently, clang postpones all semantic analysis of unary operators with operands of pointer/pointer to member/array/function type until instantiation whenever that type is dependent (e.g. `T*` where `T` is a type template parameter). Consequently, the uninstantiated AST nodes all have the type `ASTContext::DependentTy` (which, for the purposes of #90152, is undesirable as that type may be the current instantiation! (e.g. `*this`)) This patch moves the point at which we perform semantic analysis for such expression to be prior to instantiation.
…g 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
It was trying to call a storage() method, which doesn't exist in PlacementStorage. This was uncovered by a recent Clang change: llvm/llvm-project#90152 Upstream-Status: Backport [https://chromium-review.googlesource.com/c/chromium/src/+/5515154] Bug: 338536260 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5515154 Auto-Submit: Hans Wennborg <hans@chromium.org> Commit-Queue: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Commit-Queue: Hans Wennborg <hans@chromium.org> Cr-Commit-Position: refs/heads/main@{#1296238} Change-Id: Ib03c42053429b33af592894f0ce39ea4faaf68ad Pick-to: 118-based Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/586023 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
It was referring to non-existing members of Iterator. Presumably this wasn't noticed because the compiler was doing the name lookup at instantiation time and this function was never instantiated, but a recent Clang change [1] uncovered it. 1. llvm/llvm-project#90152 Upstream-Status: Backport [https://chromium-review.googlesource.com/c/chromium/src/+/5512719] Bug: 338536260 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5512719 Auto-Submit: Hans Wennborg <hans@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Commit-Queue: Daniel Cheng <dcheng@chromium.org> Cr-Commit-Position: refs/heads/main@{#1296463} Pick-to: 118-based Change-Id: I2192aab954f58b6b555822dea6801fddcb99f8f0 Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/586000 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
The code was referring to a member which didn't exist. This was uncovered by a recent Clang change [1] which made the compiler lookup these names at template parse time rather than instantiation time. 1. llvm/llvm-project#90152 Upstream-Status: Backport [google/quiche@c1af894] Change-Id: I50bc7df75698a699365aa9752de9c0a9b0b0591f Pick-to: 118-based Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/564494 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
It was referring to non-existing members of Iterator. Presumably this wasn't noticed because the compiler was doing the name lookup at instantiation time and this function was never instantiated, but a recent Clang change [1] uncovered it. 1. llvm/llvm-project#90152 Upstream-Status: Backport [https://chromium-review.googlesource.com/c/chromium/src/+/5512719] Bug: 338536260 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5512719 Auto-Submit: Hans Wennborg <hans@chromium.org> Reviewed-by: Daniel Cheng <dcheng@chromium.org> Commit-Queue: Daniel Cheng <dcheng@chromium.org> Cr-Commit-Position: refs/heads/main@{#1296463} Change-Id: I2192aab954f58b6b555822dea6801fddcb99f8f0 Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/586000 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu> (cherry picked from commit a674222) Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/586335 Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> Reviewed-by: Khem Raj <raj.khem@gmail.com>
The code was referring to a member which didn't exist. This was uncovered by a recent Clang change [1] which made the compiler lookup these names at template parse time rather than instantiation time. 1. llvm/llvm-project#90152 Upstream-Status: Backport [google/quiche@c1af894] Change-Id: I50bc7df75698a699365aa9752de9c0a9b0b0591f Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/564494 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu> (cherry picked from commit 502a476) Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/586337 Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This backports upstream change: https://quiche.googlesource.com/quiche/+/c1af894e0f5c4f732a983e7c93227854e203570e Fix QuicIntervalDeque::Iterator::operator+= The code was referring to a member which didn't exist. This was uncovered by a recent Clang change [1] which made the compiler lookup these names at template parse time rather than instantiation time. 1. llvm/llvm-project#90152 PiperOrigin-RevId: 630952202 Test: presubmit Change-Id: I82121b22326dd0a5b0db65463b11f174b6aa81fe
cherry-picked: 8009bbe sdkrystian@gmail.com Tue Apr 30 14:25:09 2024 -0400 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) 3191e0b sdkrystian@gmail.com Fri May 3 17:07:52 2024 -0400 [Clang][Sema] Fix template name lookup for operator= (llvm#90999) 62b5b61 sdkrystian@gmail.com Wed May 8 20:49:59 2024 -0400 [Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (llvm#91498) 75ebcbf sdkrystian@gmail.com Thu May 9 16:34:40 2024 -0400 [Clang][Sema] Revert changes to operator= lookup in templated classes from llvm#91498, llvm#90999, and llvm#90152 (llvm#91620) 596a9c1 sdkrystian@gmail.com Mon May 13 12:24:46 2024 -0400 [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (llvm#91972) fd87d76 sdkrystian@gmail.com Mon May 20 13:55:01 2024 -0400 [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (llvm#92318) e75b58c sdkrystian@gmail.com Mon May 20 14:50:58 2024 -0400 [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (llvm#92449) bae2c54 serebrennikov.vladislav@gmail.com Mon Jul 1 20:55:57 2024 +0300 [clang][NFC] Move documentation of `Sema` functions into `Sema.h` e6d305e dzenis@richard.lv Mon Sep 4 16:54:42 2023 +0200 Add support of Windows Trace Logging macros Change-Id: I521b2ebabd7eb9a0df78c577992bfd8508ba44fd
Where optional<T> inherits optional<T>::construct via a series of classes, optional<T&> does not. This means that optional<T&>::emplace() was broken and called into a member function that did not exist. This replaces the functionality to make optional<T&>::emplace() change the stored reference to the new one. Note that it does _not_ emplace the referee, as this would lead to questionable behavior when the optional holds nullopt. This was revealed by a change in LLVM, see llvm/llvm-project#90152 and ROCm#404.
Where optional<T> inherits optional<T>::construct via a series of classes, optional<T&> does not. This means that optional<T&>::emplace() was broken and called into a member function that did not exist. This replaces the functionality to make optional<T&>::emplace() change the stored reference to the new one. Note that it does _not_ emplace the referee, as this would lead to questionable behavior when the optional holds nullopt. This was revealed by a change in LLVM, see llvm/llvm-project#90152 and ROCm#404.
Where optional<T> inherits optional<T>::construct via a series of classes, optional<T&> does not. This means that optional<T&>::emplace() was broken and called into a member function that did not exist. This replaces the functionality to make optional<T&>::emplace() change the stored reference to the new one. Note that it does _not_ emplace the referee, as this would lead to questionable behavior when the optional holds nullopt. This was revealed by a change in LLVM, see llvm/llvm-project#90152 and ROCm#404.
* Workaround compiler issue for inclusive/exclusive scan with FixedVector items * Added missing explicit qualification of pow * Ensure that {cr}begin works with types that pull in namespace std via ADL * Various and sundry fixes for Thrust's CPP backends. * Expose thrust's contiguous iterator unwrap helpers * Several improvements to zip_iterator/zip_function * Fix thrust::optional<T&>::emplace() Where optional<T> inherits optional<T>::construct via a series of classes, optional<T&> does not. This means that optional<T&>::emplace() was broken and called into a member function that did not exist. This replaces the functionality to make optional<T&>::emplace() change the stored reference to the new one. Note that it does _not_ emplace the referee, as this would lead to questionable behavior when the optional holds nullopt. This was revealed by a change in LLVM, see llvm/llvm-project#90152 and #404. * Fix issues that came up with building cuDF with main * Bump version to 2.5.0 * Add test for CUDA backend to make sure that thrust::counting_iterator is supported from cuda::std * Remove redundant thrust dialect conditional * Move visibility attributes to cccl * Fix logic for including libcudacxx headers * add find_first_of to HIPSTDPAR * fix memory free on error * fix review comments * fix rocprim::find_first_of usage * fix copy_if to work with large data types * fix tests * fix copyright date * add another operator== for large_data add large_data only to copy tests * add casts to make code clearer * Added search and find_end to hipstdpar * Fix compile warning * Add missing CHANGELOG entry for CCCL 2.5.0 update * Add rocPRIM's adjacent_find to hipstdpar * Consistently use thrust::equal_to as default operator * add change log * Add search_n support * fix windows build failed * Add overload under std namespace * add typename before * add typename before * Work in progress * Work in progress * Apply 1 suggestion(s) to 1 file(s) Co-authored-by: Milo Lurati <milo@streamhpc.com> * fix function name mistakes * Set c++ version to 17 and create warning * Fix no_discard warning c++17 * Build for both c++ 14 and 17 * Fix tuple test for c++17 * Add new documentation for tuple.h --------- Co-authored-by: Beatriz Navidad Vilches <beatriz@streamhpc.com> Co-authored-by: Robin Voetter <robin@streamhpc.com> Co-authored-by: Bence Parajdi <bence@streamhpc.com> Co-authored-by: Cenxuan Tian <cenxuan@streamhpc.com> Co-authored-by: Milo Lurati <milo@streamhpc.com>
Reapplies #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).