diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp | 175 |
1 files changed, 132 insertions, 43 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp index 545ac27..f6accb1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -538,13 +539,42 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, namespace { // Callback to only accept typo corrections that are either a ValueDecl or a -// FunctionTemplateDecl. +// FunctionTemplateDecl and are declared in the current record or, for a C++ +// classes, one of its base classes. class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback { public: + explicit RecordMemberExprValidatorCCC(const RecordType *RTy) + : Record(RTy->getDecl()) {} + virtual bool ValidateCandidate(const TypoCorrection &candidate) { NamedDecl *ND = candidate.getCorrectionDecl(); - return ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)); + // Don't accept candidates that cannot be member functions, constants, + // variables, or templates. + if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) + return false; + + // Accept candidates that occur in the current record. + if (Record->containsDecl(ND)) + return true; + + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) { + // Accept candidates that occur in any of the current class' base classes. + for (CXXRecordDecl::base_class_const_iterator BS = RD->bases_begin(), + BSEnd = RD->bases_end(); + BS != BSEnd; ++BS) { + if (const RecordType *BSTy = dyn_cast_or_null<RecordType>( + BS->getType().getTypePtrOrNull())) { + if (BSTy->getDecl()->containsDecl(ND)) + return true; + } + } + } + + return false; } + + private: + const RecordDecl *const Record; }; } @@ -600,24 +630,31 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // We didn't find anything with the given name, so try to correct // for typos. DeclarationName Name = R.getLookupName(); - RecordMemberExprValidatorCCC Validator; + RecordMemberExprValidatorCCC Validator(RTy); TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), NULL, &SS, Validator, DC); R.clear(); - if (NamedDecl *ND = Corrected.getCorrectionDecl()) { - std::string CorrectedStr( - Corrected.getAsString(SemaRef.getLangOpts())); - std::string CorrectedQuotedStr( - Corrected.getQuoted(SemaRef.getLangOpts())); + if (Corrected.isResolved() && !Corrected.isKeyword()) { R.setLookupName(Corrected.getCorrection()); - R.addDecl(ND); - SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << DC << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), - CorrectedStr); - SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) - << ND->getDeclName(); + 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(0); + 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()); } return false; @@ -687,6 +724,7 @@ ExprResult Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, SourceLocation loc, IndirectFieldDecl *indirectField, + DeclAccessPair foundDecl, Expr *baseObjectExpr, SourceLocation opLoc) { // First, build the expression that refers to the base object. @@ -764,15 +802,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, if (!baseVariable) { FieldDecl *field = cast<FieldDecl>(*FI); - // FIXME: use the real found-decl info! - DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess()); - // Make a nameInfo that properly uses the anonymous name. DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer, EmptySS, field, foundDecl, memberNameInfo).take(); + if (!result) + return ExprError(); + baseObjectIsPointer = false; // FIXME: check qualified member access @@ -783,14 +821,15 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, while (FI != FEnd) { FieldDecl *field = cast<FieldDecl>(*FI++); - + // FIXME: these are somewhat meaningless DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); - DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess()); - + DeclAccessPair fakeFoundDecl = + DeclAccessPair::make(field, field->getAccess()); + result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false, - (FI == FEnd? SS : EmptySS), field, - foundDecl, memberNameInfo).take(); + (FI == FEnd? SS : EmptySS), field, + fakeFoundDecl, memberNameInfo).take(); } return Owned(result); @@ -845,7 +884,54 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, BaseType = BaseType->castAs<PointerType>()->getPointeeType(); } R.setBaseObjectType(BaseType); - + + LambdaScopeInfo *const CurLSI = getCurLambda(); + // If this is an implicit member reference and the overloaded + // name refers to both static and non-static member functions + // (i.e. BaseExpr is null) and if we are currently processing a lambda, + // check if we should/can capture 'this'... + // Keep this example in mind: + // struct X { + // void f(int) { } + // static void f(double) { } + // + // int g() { + // auto L = [=](auto a) { + // return [](int i) { + // return [=](auto b) { + // f(b); + // //f(decltype(a){}); + // }; + // }; + // }; + // auto M = L(0.0); + // auto N = M(3); + // N(5.32); // OK, must not error. + // return 0; + // } + // }; + // + if (!BaseExpr && CurLSI) { + SourceLocation Loc = R.getNameLoc(); + if (SS.getRange().isValid()) + Loc = SS.getRange().getBegin(); + DeclContext *EnclosingFunctionCtx = CurContext->getParent()->getParent(); + // If the enclosing function is not dependent, then this lambda is + // capture ready, so if we can capture this, do so. + if (!EnclosingFunctionCtx->isDependentContext()) { + // If the current lambda and all enclosing lambdas can capture 'this' - + // then go ahead and capture 'this' (since our unresolved overload set + // contains both static and non-static member functions). + if (!CheckCXXThisCapture(Loc, /*Explcit*/false, /*Diagnose*/false)) + CheckCXXThisCapture(Loc); + } else if (CurContext->isDependentContext()) { + // ... since this is an implicit member reference, that might potentially + // involve a 'this' capture, mark 'this' for potential capture in + // enclosing lambdas. + if (CurLSI->ImpCaptureStyle != CurLSI->ImpCap_None) + CurLSI->addPotentialThisCapture(Loc); + } + } const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); DeclarationName MemberName = MemberNameInfo.getName(); SourceLocation MemberLoc = MemberNameInfo.getLoc(); @@ -974,7 +1060,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // We may have found a field within an anonymous union or struct // (C++ [class.union]). return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, - BaseExpr, OpLoc); + FoundDecl, BaseExpr, + OpLoc); if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, @@ -1117,10 +1204,13 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // foo->bar // This is actually well-formed in C++ if MyRecord has an // overloaded operator->, but that should have been dealt with - // by now. - Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() - << FixItHint::CreateReplacement(OpLoc, "."); + // by now--or a diagnostic message already issued if a problem + // was encountered while looking for the overloaded operator->. + if (!getLangOpts().CPlusPlus) { + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "."); + } IsArrow = false; } else if (BaseType->isFunctionType()) { goto fail; @@ -1190,14 +1280,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, LookupMemberName, NULL, NULL, Validator, IDecl)) { IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>(); - Diag(R.getNameLoc(), - diag::err_typecheck_member_reference_ivar_suggest) - << IDecl->getDeclName() << MemberName << IV->getDeclName() - << FixItHint::CreateReplacement(R.getNameLoc(), - IV->getNameAsString()); - Diag(IV->getLocation(), diag::note_previous_decl) - << IV->getDeclName(); - + diagnoseTypo(Corrected, + PDiag(diag::err_typecheck_member_reference_ivar_suggest) + << IDecl->getDeclName() << MemberName); + // Figure out the class that declares the ivar. assert(!ClassDeclared); Decl *D = cast<Decl>(IV->getDeclContext()); @@ -1297,7 +1383,7 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, MemberLoc); if (Level != DiagnosticsEngine::Ignored) - getCurFunction()->recordUseOfWeak(Result); + recordUseOfEvaluatedWeak(Result); } } @@ -1348,8 +1434,9 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (DiagnoseUseOfDecl(OMD, MemberLoc)) return ExprError(); Selector SetterSel = - SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), Member); + SelectorTable::constructSetterSelector(PP.getIdentifierTable(), + PP.getSelectorTable(), + Member); ObjCMethodDecl *SMD = 0; if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0, SetterSel, Context)) @@ -1396,8 +1483,9 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. Selector SetterSel = - SelectorTable::constructSetterName(PP.getIdentifierTable(), - PP.getSelectorTable(), Member); + SelectorTable::constructSetterSelector(PP.getIdentifierTable(), + PP.getSelectorTable(), + Member); ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' @@ -1670,7 +1758,8 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, // (C++ [class.union]). // FIXME: template-ids inside anonymous structs? if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>()) - return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD); + return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD, + R.begin().getPair()); // If this is known to be an instance access, go ahead and build an // implicit 'this' expression now. |