aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaExprMember.cpp
diff options
context:
space:
mode:
authorCorentin Jabot <corentinjabot@gmail.com>2022-01-27 13:55:08 +0100
committerCorentin Jabot <corentinjabot@gmail.com>2023-10-02 14:33:02 +0200
commitaf4751738db89a142a8880c782d12d4201b222a8 (patch)
treeb58f2c515b189904f4b598a06f0af0e642343b2c /clang/lib/Sema/SemaExprMember.cpp
parentbc7d88faf1a595ab59952a2054418cdd0d9eeee8 (diff)
downloadllvm-af4751738db89a142a8880c782d12d4201b222a8.zip
llvm-af4751738db89a142a8880c782d12d4201b222a8.tar.gz
llvm-af4751738db89a142a8880c782d12d4201b222a8.tar.bz2
[C++] Implement "Deducing this" (P0847R7)
This patch implements P0847R7 (partially), CWG2561 and CWG2653. Reviewed By: aaron.ballman, #clang-language-wg Differential Revision: https://reviews.llvm.org/D140828
Diffstat (limited to 'clang/lib/Sema/SemaExprMember.cpp')
-rw-r--r--clang/lib/Sema/SemaExprMember.cpp65
1 files changed, 46 insertions, 19 deletions
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index fe92215..bd85b54 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -46,7 +46,7 @@ enum IMAKind {
/// The reference may be to an instance member, but it might be invalid if
/// so, because the context is not an instance method.
- IMA_Mixed_StaticContext,
+ IMA_Mixed_StaticOrExplicitContext,
/// The reference may be to an instance member, but it is invalid if
/// so, because the context is from an unrelated class.
@@ -63,7 +63,7 @@ enum IMAKind {
/// The reference may be to an unresolved using declaration and the
/// context is not an instance method.
- IMA_Unresolved_StaticContext,
+ IMA_Unresolved_StaticOrExplicitContext,
// The reference refers to a field which is not a member of the containing
// class, which is allowed because we're in C++11 mode and the context is
@@ -72,7 +72,7 @@ enum IMAKind {
/// All possible referrents are instance members and the current
/// context is not an instance method.
- IMA_Error_StaticContext,
+ IMA_Error_StaticOrExplicitContext,
/// All possible referrents are instance members of an unrelated
/// class.
@@ -91,11 +91,14 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
- bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() &&
- (!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic());
+ bool isStaticOrExplicitContext =
+ SemaRef.CXXThisTypeOverride.isNull() &&
+ (!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic() ||
+ cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction());
if (R.isUnresolvableResult())
- return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
+ return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext
+ : IMA_Unresolved;
// Collect all the declaring classes of instance members we find.
bool hasNonInstance = false;
@@ -152,12 +155,12 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
// If the current context is not an instance method, it can't be
// an implicit member reference.
- if (isStaticContext) {
+ if (isStaticOrExplicitContext) {
if (hasNonInstance)
- return IMA_Mixed_StaticContext;
+ return IMA_Mixed_StaticOrExplicitContext;
return AbstractInstanceResult ? AbstractInstanceResult
- : IMA_Error_StaticContext;
+ : IMA_Error_StaticOrExplicitContext;
}
CXXRecordDecl *contextClass;
@@ -167,7 +170,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
contextClass = RD;
else
return AbstractInstanceResult ? AbstractInstanceResult
- : IMA_Error_StaticContext;
+ : IMA_Error_StaticOrExplicitContext;
// [class.mfct.non-static]p3:
// ...is used in the body of a non-static member function of class X,
@@ -214,14 +217,31 @@ static void diagnoseInstanceReference(Sema &SemaRef,
CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext());
bool InStaticMethod = Method && Method->isStatic();
+ bool InExplicitObjectMethod =
+ Method && Method->isExplicitObjectMemberFunction();
bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep);
+ std::string Replacement;
+ if (InExplicitObjectMethod) {
+ DeclarationName N = Method->getParamDecl(0)->getDeclName();
+ if (!N.isEmpty()) {
+ Replacement.append(N.getAsString());
+ Replacement.append(".");
+ }
+ }
if (IsField && InStaticMethod)
// "invalid use of member 'x' in static member function"
- SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
- << Range << nameInfo.getName();
- else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod &&
- !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass))
+ SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)
+ << Range << nameInfo.getName() << /*static*/ 0;
+ else if (IsField && InExplicitObjectMethod) {
+ auto Diag = SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method)
+ << Range << nameInfo.getName() << /*explicit*/ 1;
+ if (!Replacement.empty())
+ Diag << FixItHint::CreateInsertion(Loc, Replacement);
+ } else if (ContextClass && RepClass && SS.isEmpty() &&
+ !InExplicitObjectMethod && !InStaticMethod &&
+ !RepClass->Equals(ContextClass) &&
+ RepClass->Encloses(ContextClass))
// Unqualified lookup in a non-static member function found a member of an
// enclosing class.
SemaRef.Diag(Loc, diag::err_nested_non_static_member_use)
@@ -229,9 +249,16 @@ static void diagnoseInstanceReference(Sema &SemaRef,
else if (IsField)
SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
<< nameInfo.getName() << Range;
- else
+ else if (!InExplicitObjectMethod)
SemaRef.Diag(Loc, diag::err_member_call_without_object)
- << Range;
+ << Range << /*static*/ 0;
+ else {
+ const auto *Callee = dyn_cast<CXXMethodDecl>(Rep);
+ auto Diag = SemaRef.Diag(Loc, diag::err_member_call_without_object)
+ << Range << Callee->isExplicitObjectMemberFunction();
+ if (!Replacement.empty())
+ Diag << FixItHint::CreateInsertion(Loc, Replacement);
+ }
}
/// Builds an expression which might be an implicit member expression.
@@ -255,13 +282,13 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr(
[[fallthrough]];
case IMA_Static:
case IMA_Abstract:
- case IMA_Mixed_StaticContext:
- case IMA_Unresolved_StaticContext:
+ case IMA_Mixed_StaticOrExplicitContext:
+ case IMA_Unresolved_StaticOrExplicitContext:
if (TemplateArgs || TemplateKWLoc.isValid())
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);
- case IMA_Error_StaticContext:
+ case IMA_Error_StaticOrExplicitContext:
case IMA_Error_Unrelated:
diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
R.getLookupNameInfo());