"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/Sema/SemaExprMember.cpp" between
cfe-8.0.1.src.tar.xz and cfe-9.0.0.src.tar.xz

About: Clang is an LLVM front end for the C, C++, and Objective-C languages. Clang aims to provide a better user experience through expressive diagnostics, a high level of conformance to language standards, fast compilation, and low memory use.

SemaExprMember.cpp  (cfe-8.0.1.src.tar.xz):SemaExprMember.cpp  (cfe-9.0.0.src.tar.xz)
//===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===// //===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===//
// //
// The LLVM Compiler Infrastructure // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// // See https://llvm.org/LICENSE.txt for license information.
// This file is distributed under the University of Illinois Open Source // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// License. See LICENSE.TXT for details.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This file implements semantic analysis member access expressions. // This file implements semantic analysis member access expressions.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "clang/Sema/Overload.h" #include "clang/Sema/Overload.h"
#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclObjC.h"
skipping to change at line 594 skipping to change at line 593
R.getRepresentativeDecl(), R.getRepresentativeDecl(),
R.getLookupNameInfo()); R.getLookupNameInfo());
return true; return true;
} }
namespace { namespace {
// Callback to only accept typo corrections that are either a ValueDecl or a // Callback to only accept typo corrections that are either a ValueDecl or a
// FunctionTemplateDecl and are declared in the current record or, for a C++ // FunctionTemplateDecl and are declared in the current record or, for a C++
// classes, one of its base classes. // classes, one of its base classes.
class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback { class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
public: public:
explicit RecordMemberExprValidatorCCC(const RecordType *RTy) explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
: Record(RTy->getDecl()) { : Record(RTy->getDecl()) {
// Don't add bare keywords to the consumer since they will always fail // Don't add bare keywords to the consumer since they will always fail
// validation by virtue of not being associated with any decls. // validation by virtue of not being associated with any decls.
WantTypeSpecifiers = false; WantTypeSpecifiers = false;
WantExpressionKeywords = false; WantExpressionKeywords = false;
WantCXXNamedCasts = false; WantCXXNamedCasts = false;
WantFunctionLikeCasts = false; WantFunctionLikeCasts = false;
WantRemainingKeywords = false; WantRemainingKeywords = false;
skipping to change at line 632 skipping to change at line 631
dyn_cast_or_null<RecordType>(BS.getType().getTypePtrOrNull())) { dyn_cast_or_null<RecordType>(BS.getType().getTypePtrOrNull())) {
if (BSTy->getDecl()->containsDecl(ND)) if (BSTy->getDecl()->containsDecl(ND))
return true; return true;
} }
} }
} }
return false; return false;
} }
std::unique_ptr<CorrectionCandidateCallback> clone() override {
return llvm::make_unique<RecordMemberExprValidatorCCC>(*this);
}
private: private:
const RecordDecl *const Record; const RecordDecl *const Record;
}; };
} }
static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
Expr *BaseExpr, Expr *BaseExpr,
const RecordType *RTy, const RecordType *RTy,
SourceLocation OpLoc, bool IsArrow, SourceLocation OpLoc, bool IsArrow,
skipping to change at line 700 skipping to change at line 703
SourceLocation TypoLoc = R.getNameLoc(); SourceLocation TypoLoc = R.getNameLoc();
struct QueryState { struct QueryState {
Sema &SemaRef; Sema &SemaRef;
DeclarationNameInfo NameInfo; DeclarationNameInfo NameInfo;
Sema::LookupNameKind LookupKind; Sema::LookupNameKind LookupKind;
Sema::RedeclarationKind Redecl; Sema::RedeclarationKind Redecl;
}; };
QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(), QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
R.redeclarationKind()}; R.redeclarationKind()};
RecordMemberExprValidatorCCC CCC(RTy);
TE = SemaRef.CorrectTypoDelayed( TE = SemaRef.CorrectTypoDelayed(
R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC,
llvm::make_unique<RecordMemberExprValidatorCCC>(RTy),
[=, &SemaRef](const TypoCorrection &TC) { [=, &SemaRef](const TypoCorrection &TC) {
if (TC) { if (TC) {
assert(!TC.isKeyword() && assert(!TC.isKeyword() &&
"Got a keyword as a correction for a member!"); "Got a keyword as a correction for a member!");
bool DroppedSpecifier = bool DroppedSpecifier =
TC.WillReplaceSpecifier() && TC.WillReplaceSpecifier() &&
Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts()); Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts());
SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest) SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
<< Typo << DC << DroppedSpecifier << Typo << DC << DroppedSpecifier
<< SS.getRange()); << SS.getRange());
skipping to change at line 893 skipping to change at line 896
MSPropertyDecl *PD, MSPropertyDecl *PD,
const DeclarationNameInfo &NameInfo) { const DeclarationNameInfo &NameInfo) {
// Property names are always simple identifiers and therefore never // Property names are always simple identifiers and therefore never
// require any interesting additional storage. // require any interesting additional storage.
return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow, return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow,
S.Context.PseudoObjectTy, VK_LValue, S.Context.PseudoObjectTy, VK_LValue,
SS.getWithLocInContext(S.Context), SS.getWithLocInContext(S.Context),
NameInfo.getLoc()); NameInfo.getLoc());
} }
/// Build a MemberExpr AST node. MemberExpr *Sema::BuildMemberExpr(
static MemberExpr *BuildMemberExpr( Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS,
Sema &SemaRef, ASTContext &C, Expr *Base, bool isArrow, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
SourceLocation OpLoc, const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
ValueDecl *Member, DeclAccessPair FoundDecl, QualType Ty, ExprValueKind VK, ExprObjectKind OK,
const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, const TemplateArgumentListInfo *TemplateArgs) {
ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr) { NestedNameSpecifierLoc NNS =
assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue"); SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc();
MemberExpr *E = MemberExpr::Create( return BuildMemberExpr(Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member,
C, Base, isArrow, OpLoc, SS.getWithLocInContext(C), TemplateKWLoc, Member, FoundDecl, HadMultipleCandidates, MemberNameInfo, Ty,
FoundDecl, MemberNameInfo, TemplateArgs, Ty, VK, OK); VK, OK, TemplateArgs);
SemaRef.MarkMemberReferenced(E); }
MemberExpr *Sema::BuildMemberExpr(
Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
QualType Ty, ExprValueKind VK, ExprObjectKind OK,
const TemplateArgumentListInfo *TemplateArgs) {
assert((!IsArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
MemberExpr *E =
MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc,
Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty,
VK, OK, getNonOdrUseReasonInCurrentContext(Member));
E->setHadMultipleCandidates(HadMultipleCandidates);
MarkMemberReferenced(E);
return E; return E;
} }
/// Determine if the given scope is within a function-try-block handler. /// Determine if the given scope is within a function-try-block handler.
static bool IsInFnTryBlockHandler(const Scope *S) { static bool IsInFnTryBlockHandler(const Scope *S) {
// Walk the scope stack until finding a FnTryCatchScope, or leave the // Walk the scope stack until finding a FnTryCatchScope, or leave the
// function scope. If a FnTryCatchScope is found, check whether the TryScope // function scope. If a FnTryCatchScope is found, check whether the TryScope
// flag is set. If it is not, it's a function-try-block handler. // flag is set. If it is not, it's a function-try-block handler.
for (; S != S->getFnParent(); S = S->getParent()) { for (; S != S->getFnParent(); S = S->getParent()) {
if (S->getFlags() & Scope::FnTryCatchScope) if (S->getFlags() & Scope::FnTryCatchScope)
skipping to change at line 1091 skipping to change at line 1108
R.getLookupNameInfo(), TemplateKWLoc); R.getLookupNameInfo(), TemplateKWLoc);
if (!MemberDecl) if (!MemberDecl)
return ExprError(); return ExprError();
} }
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl, return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl,
FoundDecl, TemplateArgs); FoundDecl, TemplateArgs);
} }
SourceLocation Loc = R.getNameLoc(); SourceLocation Loc = R.getNameLoc();
if (SS.getRange().isValid()) if (SS.getRange().isValid())
Loc = SS.getRange().getBegin(); Loc = SS.getRange().getBegin();
CheckCXXThisCapture(Loc); BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true);
BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true);
} }
// Check the use of this member. // Check the use of this member.
if (DiagnoseUseOfDecl(MemberDecl, MemberLoc)) if (DiagnoseUseOfDecl(MemberDecl, MemberLoc))
return ExprError(); return ExprError();
if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl))
return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl, return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl,
MemberNameInfo); MemberNameInfo);
skipping to change at line 1115 skipping to change at line 1131
MemberNameInfo); MemberNameInfo);
if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
// We may have found a field within an anonymous union or struct // We may have found a field within an anonymous union or struct
// (C++ [class.union]). // (C++ [class.union]).
return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
FoundDecl, BaseExpr, FoundDecl, BaseExpr,
OpLoc); OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS, return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var,
TemplateKWLoc, Var, FoundDecl, MemberNameInfo, FoundDecl, /*HadMultipleCandidates=*/false,
Var->getType().getNonReferenceType(), VK_LValue, MemberNameInfo, Var->getType().getNonReferenceType(),
OK_Ordinary); VK_LValue, OK_Ordinary);
} }
if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) { if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
ExprValueKind valueKind; ExprValueKind valueKind;
QualType type; QualType type;
if (MemberFn->isInstance()) { if (MemberFn->isInstance()) {
valueKind = VK_RValue; valueKind = VK_RValue;
type = Context.BoundMemberTy; type = Context.BoundMemberTy;
} else { } else {
valueKind = VK_LValue; valueKind = VK_LValue;
type = MemberFn->getType(); type = MemberFn->getType();
} }
return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS, return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc,
TemplateKWLoc, MemberFn, FoundDecl, MemberNameInfo, MemberFn, FoundDecl, /*HadMultipleCandidates=*/false,
type, valueKind, OK_Ordinary); MemberNameInfo, type, valueKind, OK_Ordinary);
} }
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS, return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Enum,
TemplateKWLoc, Enum, FoundDecl, MemberNameInfo, FoundDecl, /*HadMultipleCandidates=*/false,
Enum->getType(), VK_RValue, OK_Ordinary); MemberNameInfo, Enum->getType(), VK_RValue,
OK_Ordinary);
} }
if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) { if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
if (VarDecl *Var = getVarTemplateSpecialization( if (VarDecl *Var = getVarTemplateSpecialization(
*this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) *this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
return BuildMemberExpr(*this, Context, BaseExpr, IsArrow, OpLoc, SS, return BuildMemberExpr(
TemplateKWLoc, Var, FoundDecl, MemberNameInfo, BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl,
Var->getType().getNonReferenceType(), VK_LValue, /*HadMultipleCandidates=*/false, MemberNameInfo,
OK_Ordinary); Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary);
return ExprError(); return ExprError();
} }
// We found something that we didn't expect. Complain. // We found something that we didn't expect. Complain.
if (isa<TypeDecl>(MemberDecl)) if (isa<TypeDecl>(MemberDecl))
Diag(MemberLoc, diag::err_typecheck_member_reference_type) Diag(MemberLoc, diag::err_typecheck_member_reference_type)
<< MemberName << BaseType << int(IsArrow); << MemberName << BaseType << int(IsArrow);
else else
Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)
<< MemberName << BaseType << int(IsArrow); << MemberName << BaseType << int(IsArrow);
skipping to change at line 1334 skipping to change at line 1351
if (S.RequireCompleteType(OpLoc, BaseType, if (S.RequireCompleteType(OpLoc, BaseType,
diag::err_typecheck_incomplete_tag, diag::err_typecheck_incomplete_tag,
BaseExpr.get())) BaseExpr.get()))
return ExprError(); return ExprError();
ObjCInterfaceDecl *ClassDeclared = nullptr; ObjCInterfaceDecl *ClassDeclared = nullptr;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
if (!IV) { if (!IV) {
// Attempt to correct for typos in ivar names. // Attempt to correct for typos in ivar names.
auto Validator = llvm::make_unique<DeclFilterCCC<ObjCIvarDecl>>(); DeclFilterCCC<ObjCIvarDecl> Validator{};
Validator->IsObjCIvarLookup = IsArrow; Validator.IsObjCIvarLookup = IsArrow;
if (TypoCorrection Corrected = S.CorrectTypo( if (TypoCorrection Corrected = S.CorrectTypo(
R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr, R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
std::move(Validator), Sema::CTK_ErrorRecovery, IDecl)) { Validator, Sema::CTK_ErrorRecovery, IDecl)) {
IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>(); IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
S.diagnoseTypo( S.diagnoseTypo(
Corrected, Corrected,
S.PDiag(diag::err_typecheck_member_reference_ivar_suggest) S.PDiag(diag::err_typecheck_member_reference_ivar_suggest)
<< IDecl->getDeclName() << MemberName); << IDecl->getDeclName() << MemberName);
// Figure out the class that declares the ivar. // Figure out the class that declares the ivar.
assert(!ClassDeclared); assert(!ClassDeclared);
Decl *D = cast<Decl>(IV->getDeclContext()); Decl *D = cast<Decl>(IV->getDeclContext());
skipping to change at line 1805 skipping to change at line 1822
// non-static member functions, privatized by OpenMP constructs. // non-static member functions, privatized by OpenMP constructs.
if (getLangOpts().OpenMP && IsArrow && if (getLangOpts().OpenMP && IsArrow &&
!CurContext->isDependentContext() && !CurContext->isDependentContext() &&
isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) { isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
if (auto *PrivateCopy = isOpenMPCapturedDecl(Field)) { if (auto *PrivateCopy = isOpenMPCapturedDecl(Field)) {
return getOpenMPCapturedExpr(PrivateCopy, VK, OK, return getOpenMPCapturedExpr(PrivateCopy, VK, OK,
MemberNameInfo.getLoc()); MemberNameInfo.getLoc());
} }
} }
return BuildMemberExpr(*this, Context, Base.get(), IsArrow, OpLoc, SS, return BuildMemberExpr(Base.get(), IsArrow, OpLoc, &SS,
/*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl,
MemberNameInfo, MemberType, VK, OK); /*HadMultipleCandidates=*/false, MemberNameInfo,
MemberType, VK, OK);
} }
/// Builds an implicit member access expression. The current context /// Builds an implicit member access expression. The current context
/// is known to be an instance method, and the given unqualified lookup /// is known to be an instance method, and the given unqualified lookup
/// set is known to contain only instance members, at least one of which /// set is known to contain only instance members, at least one of which
/// is from an appropriate type. /// is from an appropriate type.
ExprResult ExprResult
Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc, SourceLocation TemplateKWLoc,
LookupResult &R, LookupResult &R,
skipping to change at line 1835 skipping to change at line 1853
// implicit 'this' expression now. // implicit 'this' expression now.
// 'this' expression now. // 'this' expression now.
QualType ThisTy = getCurrentThisType(); QualType ThisTy = getCurrentThisType();
assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'"); assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'");
Expr *baseExpr = nullptr; // null signifies implicit access Expr *baseExpr = nullptr; // null signifies implicit access
if (IsKnownInstance) { if (IsKnownInstance) {
SourceLocation Loc = R.getNameLoc(); SourceLocation Loc = R.getNameLoc();
if (SS.getRange().isValid()) if (SS.getRange().isValid())
Loc = SS.getRange().getBegin(); Loc = SS.getRange().getBegin();
CheckCXXThisCapture(Loc); baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true);
baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true);
} }
return BuildMemberReferenceExpr(baseExpr, ThisTy, return BuildMemberReferenceExpr(baseExpr, ThisTy,
/*OpLoc*/ SourceLocation(), /*OpLoc*/ SourceLocation(),
/*IsArrow*/ true, /*IsArrow*/ true,
SS, TemplateKWLoc, SS, TemplateKWLoc,
/*FirstQualifierInScope*/ nullptr, /*FirstQualifierInScope*/ nullptr,
R, TemplateArgs, S); R, TemplateArgs, S);
} }
 End of changes. 16 change blocks. 
42 lines changed or deleted 59 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)