aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprMember.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-01-18 16:23:48 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-01-18 16:23:48 +0000
commit06d4ba388873e6d1cfa9cd715a8935ecc8cd2097 (patch)
tree3eb853da77d46cc77c4b017525a422f9ddb1385b /lib/Sema/SemaExprMember.cpp
parent30d791273d07fac9c0c1641a0731191bca6e8606 (diff)
downloadsrc-06d4ba388873e6d1cfa9cd715a8935ecc8cd2097.tar.gz
src-06d4ba388873e6d1cfa9cd715a8935ecc8cd2097.zip
Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1):vendor/clang/clang-release_360-r226102
Notes
Notes: svn path=/vendor/clang/dist/; revision=277325 svn path=/vendor/clang/clang-release_360-r226102/; revision=277326; tag=vendor/clang/clang-release_360-r226102
Diffstat (limited to 'lib/Sema/SemaExprMember.cpp')
-rw-r--r--lib/Sema/SemaExprMember.cpp132
1 files changed, 76 insertions, 56 deletions
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index ef7898208cae..af1cf9046113 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -10,7 +10,7 @@
// This file implements semantic analysis member access expressions.
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Overload.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -21,6 +21,7 @@
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
using namespace clang;
using namespace sema;
@@ -89,7 +90,6 @@ enum IMAKind {
/// conservatively answer "yes", in which case some errors will simply
/// not be caught until template-instantiation.
static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
- Scope *CurScope,
const LookupResult &R) {
assert(!R.empty() && (*R.begin())->isCXXClassMember());
@@ -204,6 +204,9 @@ static void diagnoseInstanceReference(Sema &SemaRef,
SourceRange Range(Loc);
if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
+ // Look through using shadow decls and aliases.
+ Rep = Rep->getUnderlyingDecl();
+
DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext();
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC);
CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr;
@@ -236,7 +239,7 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
- switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) {
+ switch (ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true);
@@ -536,9 +539,17 @@ namespace {
// FunctionTemplateDecl and are declared in the current record or, for a C++
// classes, one of its base classes.
class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
- public:
+public:
explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
- : Record(RTy->getDecl()) {}
+ : Record(RTy->getDecl()) {
+ // 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;
+ WantExpressionKeywords = false;
+ WantCXXNamedCasts = false;
+ WantFunctionLikeCasts = false;
+ WantRemainingKeywords = false;
+ }
bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
@@ -554,8 +565,8 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) {
// Accept candidates that occur in any of the current class' base classes.
for (const auto &BS : RD->bases()) {
- if (const RecordType *BSTy = dyn_cast_or_null<RecordType>(
- BS.getType().getTypePtrOrNull())) {
+ if (const RecordType *BSTy =
+ dyn_cast_or_null<RecordType>(BS.getType().getTypePtrOrNull())) {
if (BSTy->getDecl()->containsDecl(ND))
return true;
}
@@ -565,17 +576,19 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
return false;
}
- private:
+private:
const RecordDecl *const Record;
};
}
-static bool
-LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
- SourceRange BaseRange, const RecordType *RTy,
- SourceLocation OpLoc, CXXScopeSpec &SS,
- bool HasTemplateArgs) {
+static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
+ Expr *BaseExpr,
+ const RecordType *RTy,
+ SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS, bool HasTemplateArgs,
+ TypoExpr *&TE) {
+ SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
RecordDecl *RDecl = RTy->getDecl();
if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
@@ -600,7 +613,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
if (SemaRef.RequireCompleteDeclContext(SS, DC)) {
SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag)
- << SS.getRange() << DC;
+ << SS.getRange() << DC;
return true;
}
@@ -608,47 +621,48 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
if (!isa<TypeDecl>(DC)) {
SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass)
- << DC << SS.getRange();
+ << DC << SS.getRange();
return true;
}
}
// The record definition is complete, now look up the member.
- SemaRef.LookupQualifiedName(R, DC);
+ SemaRef.LookupQualifiedName(R, DC, SS);
if (!R.empty())
return false;
- // We didn't find anything with the given name, so try to correct
- // for typos.
- DeclarationName Name = R.getLookupName();
- RecordMemberExprValidatorCCC Validator(RTy);
- TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),
- R.getLookupKind(), nullptr,
- &SS, Validator,
- Sema::CTK_ErrorRecovery, DC);
- R.clear();
- if (Corrected.isResolved() && !Corrected.isKeyword()) {
- R.setLookupName(Corrected.getCorrection());
- for (TypoCorrection::decl_iterator DI = Corrected.begin(),
- DIEnd = Corrected.end();
- DI != DIEnd; ++DI) {
- R.addDecl(*DI);
- }
- R.resolveKind();
-
- // If we're typo-correcting to an overloaded name, we don't yet have enough
- // information to do overload resolution, so we don't know which previous
- // declaration to point to.
- if (Corrected.isOverloaded())
- Corrected.setCorrectionDecl(nullptr);
- bool DroppedSpecifier =
- Corrected.WillReplaceSpecifier() &&
- Name.getAsString() == Corrected.getAsString(SemaRef.getLangOpts());
- SemaRef.diagnoseTypo(Corrected,
- SemaRef.PDiag(diag::err_no_member_suggest)
- << Name << DC << DroppedSpecifier << SS.getRange());
- }
+ DeclarationName Typo = R.getLookupName();
+ SourceLocation TypoLoc = R.getNameLoc();
+ TE = SemaRef.CorrectTypoDelayed(
+ R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS,
+ llvm::make_unique<RecordMemberExprValidatorCCC>(RTy),
+ [=, &SemaRef](const TypoCorrection &TC) {
+ if (TC) {
+ assert(!TC.isKeyword() &&
+ "Got a keyword as a correction for a member!");
+ bool DroppedSpecifier =
+ TC.WillReplaceSpecifier() &&
+ Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts());
+ SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
+ << Typo << DC << DroppedSpecifier
+ << SS.getRange());
+ } else {
+ SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << DC << BaseRange;
+ }
+ },
+ [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {
+ R.clear(); // Ensure there's no decls lingering in the shared state.
+ R.suppressDiagnostics();
+ R.setLookupName(TC.getCorrection());
+ for (NamedDecl *ND : TC)
+ R.addDecl(ND);
+ R.resolveKind();
+ return SemaRef.BuildMemberReferenceExpr(
+ BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),
+ nullptr, R, nullptr);
+ },
+ Sema::CTK_ErrorRecovery, DC);
return false;
}
@@ -678,12 +692,15 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
// Implicit member accesses.
if (!Base) {
+ TypoExpr *TE = nullptr;
QualType RecordTy = BaseType;
if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
- if (LookupMemberExprInRecord(*this, R, SourceRange(),
- RecordTy->getAs<RecordType>(),
- OpLoc, SS, TemplateArgs != nullptr))
+ if (LookupMemberExprInRecord(*this, R, nullptr,
+ RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
+ SS, TemplateArgs != nullptr, TE))
return ExprError();
+ if (TE)
+ return TE;
// Explicit member accesses.
} else {
@@ -1211,13 +1228,16 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Handle field access to simple records.
if (const RecordType *RTy = BaseType->getAs<RecordType>()) {
- if (LookupMemberExprInRecord(S, R, BaseExpr.get()->getSourceRange(),
- RTy, OpLoc, SS, HasTemplateArgs))
+ TypoExpr *TE = nullptr;
+ if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy,
+ OpLoc, IsArrow, SS, HasTemplateArgs, TE))
return ExprError();
// Returning valid-but-null is how we indicate to the caller that
- // the lookup result was filled in.
- return ExprResult((Expr *)nullptr);
+ // the lookup result was filled in. If typo correction was attempted and
+ // failed, the lookup result will have been cleared--that combined with the
+ // valid-but-null ExprResult will trigger the appropriate diagnostics.
+ return ExprResult(TE);
}
// Handle ivar access to Objective-C objects.
@@ -1262,11 +1282,11 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
if (!IV) {
// Attempt to correct for typos in ivar names.
- DeclFilterCCC<ObjCIvarDecl> Validator;
- Validator.IsObjCIvarLookup = IsArrow;
+ auto Validator = llvm::make_unique<DeclFilterCCC<ObjCIvarDecl>>();
+ Validator->IsObjCIvarLookup = IsArrow;
if (TypoCorrection Corrected = S.CorrectTypo(
R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr,
- Validator, Sema::CTK_ErrorRecovery, IDecl)) {
+ std::move(Validator), Sema::CTK_ErrorRecovery, IDecl)) {
IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>();
S.diagnoseTypo(
Corrected,