10b57cec5SDimitry Andric //===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements semantic analysis member access expressions. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric #include "clang/AST/ASTLambda.h" 130b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 140b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 150b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 160b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 170b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h" 180b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 190b57cec5SDimitry Andric #include "clang/Sema/Lookup.h" 200fca6ea1SDimitry Andric #include "clang/Sema/Overload.h" 210b57cec5SDimitry Andric #include "clang/Sema/Scope.h" 220b57cec5SDimitry Andric #include "clang/Sema/ScopeInfo.h" 230b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h" 240fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h" 250fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenMP.h" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace clang; 280b57cec5SDimitry Andric using namespace sema; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric /// Determines if the given class is provably not derived from all of 330b57cec5SDimitry Andric /// the prospective base classes. 340b57cec5SDimitry Andric static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record, 350b57cec5SDimitry Andric const BaseSet &Bases) { 360b57cec5SDimitry Andric auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) { 370b57cec5SDimitry Andric return !Bases.count(Base->getCanonicalDecl()); 380b57cec5SDimitry Andric }; 390b57cec5SDimitry Andric return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric enum IMAKind { 430b57cec5SDimitry Andric /// The reference is definitely not an instance member access. 440b57cec5SDimitry Andric IMA_Static, 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric /// The reference may be an implicit instance member access. 470b57cec5SDimitry Andric IMA_Mixed, 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric /// The reference may be to an instance member, but it might be invalid if 500b57cec5SDimitry Andric /// so, because the context is not an instance method. 515f757f3fSDimitry Andric IMA_Mixed_StaticOrExplicitContext, 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric /// The reference may be to an instance member, but it is invalid if 540b57cec5SDimitry Andric /// so, because the context is from an unrelated class. 550b57cec5SDimitry Andric IMA_Mixed_Unrelated, 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric /// The reference is definitely an implicit instance member access. 580b57cec5SDimitry Andric IMA_Instance, 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric /// The reference may be to an unresolved using declaration. 610b57cec5SDimitry Andric IMA_Unresolved, 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// The reference is a contextually-permitted abstract member reference. 640b57cec5SDimitry Andric IMA_Abstract, 650b57cec5SDimitry Andric 660fca6ea1SDimitry Andric /// Whether the context is static is dependent on the enclosing template (i.e. 670fca6ea1SDimitry Andric /// in a dependent class scope explicit specialization). 680fca6ea1SDimitry Andric IMA_Dependent, 690fca6ea1SDimitry Andric 700b57cec5SDimitry Andric /// The reference may be to an unresolved using declaration and the 710b57cec5SDimitry Andric /// context is not an instance method. 725f757f3fSDimitry Andric IMA_Unresolved_StaticOrExplicitContext, 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // The reference refers to a field which is not a member of the containing 750b57cec5SDimitry Andric // class, which is allowed because we're in C++11 mode and the context is 760b57cec5SDimitry Andric // unevaluated. 770b57cec5SDimitry Andric IMA_Field_Uneval_Context, 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// All possible referrents are instance members and the current 800b57cec5SDimitry Andric /// context is not an instance method. 815f757f3fSDimitry Andric IMA_Error_StaticOrExplicitContext, 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric /// All possible referrents are instance members of an unrelated 840b57cec5SDimitry Andric /// class. 850b57cec5SDimitry Andric IMA_Error_Unrelated 860b57cec5SDimitry Andric }; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric /// The given lookup names class member(s) and is not being used for 890b57cec5SDimitry Andric /// an address-of-member expression. Classify the type of access 900b57cec5SDimitry Andric /// according to whether it's possible that this reference names an 910b57cec5SDimitry Andric /// instance member. This is best-effort in dependent contexts; it is okay to 920b57cec5SDimitry Andric /// conservatively answer "yes", in which case some errors will simply 930b57cec5SDimitry Andric /// not be caught until template-instantiation. 940b57cec5SDimitry Andric static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, 950b57cec5SDimitry Andric const LookupResult &R) { 960b57cec5SDimitry Andric assert(!R.empty() && (*R.begin())->isCXXClassMember()); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); 990b57cec5SDimitry Andric 1000fca6ea1SDimitry Andric bool couldInstantiateToStatic = false; 1010fca6ea1SDimitry Andric bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull(); 1020b57cec5SDimitry Andric 1030fca6ea1SDimitry Andric if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) { 1040fca6ea1SDimitry Andric if (MD->isImplicitObjectMemberFunction()) { 1050fca6ea1SDimitry Andric isStaticOrExplicitContext = false; 1060fca6ea1SDimitry Andric // A dependent class scope function template explicit specialization 1070fca6ea1SDimitry Andric // that is neither declared 'static' nor with an explicit object 1080fca6ea1SDimitry Andric // parameter could instantiate to a static or non-static member function. 1090fca6ea1SDimitry Andric couldInstantiateToStatic = MD->getDependentSpecializationInfo(); 1100fca6ea1SDimitry Andric } 1110fca6ea1SDimitry Andric } 1120fca6ea1SDimitry Andric 1130fca6ea1SDimitry Andric if (R.isUnresolvableResult()) { 1140fca6ea1SDimitry Andric if (couldInstantiateToStatic) 1150fca6ea1SDimitry Andric return IMA_Dependent; 1165f757f3fSDimitry Andric return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext 1175f757f3fSDimitry Andric : IMA_Unresolved; 1180fca6ea1SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // Collect all the declaring classes of instance members we find. 1210b57cec5SDimitry Andric bool hasNonInstance = false; 1220b57cec5SDimitry Andric bool isField = false; 1230b57cec5SDimitry Andric BaseSet Classes; 1240b57cec5SDimitry Andric for (NamedDecl *D : R) { 1250b57cec5SDimitry Andric // Look through any using decls. 1260b57cec5SDimitry Andric D = D->getUnderlyingDecl(); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric if (D->isCXXInstanceMember()) { 1290b57cec5SDimitry Andric isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || 1300b57cec5SDimitry Andric isa<IndirectFieldDecl>(D); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); 1330b57cec5SDimitry Andric Classes.insert(R->getCanonicalDecl()); 1340b57cec5SDimitry Andric } else 1350b57cec5SDimitry Andric hasNonInstance = true; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric // If we didn't find any instance members, it can't be an implicit 1390b57cec5SDimitry Andric // member reference. 1400b57cec5SDimitry Andric if (Classes.empty()) 1410b57cec5SDimitry Andric return IMA_Static; 1420b57cec5SDimitry Andric 1430fca6ea1SDimitry Andric if (couldInstantiateToStatic) 1440fca6ea1SDimitry Andric return IMA_Dependent; 1450fca6ea1SDimitry Andric 1460b57cec5SDimitry Andric // C++11 [expr.prim.general]p12: 1470b57cec5SDimitry Andric // An id-expression that denotes a non-static data member or non-static 1480b57cec5SDimitry Andric // member function of a class can only be used: 1490b57cec5SDimitry Andric // (...) 1500b57cec5SDimitry Andric // - if that id-expression denotes a non-static data member and it 1510b57cec5SDimitry Andric // appears in an unevaluated operand. 1520b57cec5SDimitry Andric // 1530b57cec5SDimitry Andric // This rule is specific to C++11. However, we also permit this form 1540b57cec5SDimitry Andric // in unevaluated inline assembly operands, like the operand to a SIZE. 1550b57cec5SDimitry Andric IMAKind AbstractInstanceResult = IMA_Static; // happens to be 'false' 1560b57cec5SDimitry Andric assert(!AbstractInstanceResult); 1570b57cec5SDimitry Andric switch (SemaRef.ExprEvalContexts.back().Context) { 1580b57cec5SDimitry Andric case Sema::ExpressionEvaluationContext::Unevaluated: 1590b57cec5SDimitry Andric case Sema::ExpressionEvaluationContext::UnevaluatedList: 1600b57cec5SDimitry Andric if (isField && SemaRef.getLangOpts().CPlusPlus11) 1610b57cec5SDimitry Andric AbstractInstanceResult = IMA_Field_Uneval_Context; 1620b57cec5SDimitry Andric break; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric case Sema::ExpressionEvaluationContext::UnevaluatedAbstract: 1650b57cec5SDimitry Andric AbstractInstanceResult = IMA_Abstract; 1660b57cec5SDimitry Andric break; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric case Sema::ExpressionEvaluationContext::DiscardedStatement: 1690b57cec5SDimitry Andric case Sema::ExpressionEvaluationContext::ConstantEvaluated: 170349cc55cSDimitry Andric case Sema::ExpressionEvaluationContext::ImmediateFunctionContext: 1710b57cec5SDimitry Andric case Sema::ExpressionEvaluationContext::PotentiallyEvaluated: 1720b57cec5SDimitry Andric case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: 1730b57cec5SDimitry Andric break; 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // If the current context is not an instance method, it can't be 1770b57cec5SDimitry Andric // an implicit member reference. 1785f757f3fSDimitry Andric if (isStaticOrExplicitContext) { 1790b57cec5SDimitry Andric if (hasNonInstance) 1805f757f3fSDimitry Andric return IMA_Mixed_StaticOrExplicitContext; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric return AbstractInstanceResult ? AbstractInstanceResult 1835f757f3fSDimitry Andric : IMA_Error_StaticOrExplicitContext; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric CXXRecordDecl *contextClass; 18706c3fb27SDimitry Andric if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) 1880b57cec5SDimitry Andric contextClass = MD->getParent()->getCanonicalDecl(); 18906c3fb27SDimitry Andric else if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) 19006c3fb27SDimitry Andric contextClass = RD; 1910b57cec5SDimitry Andric else 19206c3fb27SDimitry Andric return AbstractInstanceResult ? AbstractInstanceResult 1935f757f3fSDimitry Andric : IMA_Error_StaticOrExplicitContext; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric // [class.mfct.non-static]p3: 1960b57cec5SDimitry Andric // ...is used in the body of a non-static member function of class X, 1970b57cec5SDimitry Andric // if name lookup (3.4.1) resolves the name in the id-expression to a 1980b57cec5SDimitry Andric // non-static non-type member of some class C [...] 1990b57cec5SDimitry Andric // ...if C is not X or a base class of X, the class member access expression 2000b57cec5SDimitry Andric // is ill-formed. 2010b57cec5SDimitry Andric if (R.getNamingClass() && 2020b57cec5SDimitry Andric contextClass->getCanonicalDecl() != 2030b57cec5SDimitry Andric R.getNamingClass()->getCanonicalDecl()) { 2040b57cec5SDimitry Andric // If the naming class is not the current context, this was a qualified 2050b57cec5SDimitry Andric // member name lookup, and it's sufficient to check that we have the naming 2060b57cec5SDimitry Andric // class as a base class. 2070b57cec5SDimitry Andric Classes.clear(); 2080b57cec5SDimitry Andric Classes.insert(R.getNamingClass()->getCanonicalDecl()); 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric // If we can prove that the current context is unrelated to all the 2120b57cec5SDimitry Andric // declaring classes, it can't be an implicit member reference (in 2130b57cec5SDimitry Andric // which case it's an error if any of those members are selected). 2140b57cec5SDimitry Andric if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) 2150b57cec5SDimitry Andric return hasNonInstance ? IMA_Mixed_Unrelated : 2160b57cec5SDimitry Andric AbstractInstanceResult ? AbstractInstanceResult : 2170b57cec5SDimitry Andric IMA_Error_Unrelated; 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric return (hasNonInstance ? IMA_Mixed : IMA_Instance); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric /// Diagnose a reference to a field with no object available. 2230b57cec5SDimitry Andric static void diagnoseInstanceReference(Sema &SemaRef, 2240b57cec5SDimitry Andric const CXXScopeSpec &SS, 2250b57cec5SDimitry Andric NamedDecl *Rep, 2260b57cec5SDimitry Andric const DeclarationNameInfo &nameInfo) { 2270b57cec5SDimitry Andric SourceLocation Loc = nameInfo.getLoc(); 2280b57cec5SDimitry Andric SourceRange Range(Loc); 2290b57cec5SDimitry Andric if (SS.isSet()) Range.setBegin(SS.getRange().getBegin()); 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric // Look through using shadow decls and aliases. 2320b57cec5SDimitry Andric Rep = Rep->getUnderlyingDecl(); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext(); 2350b57cec5SDimitry Andric CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC); 2360b57cec5SDimitry Andric CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr; 2370b57cec5SDimitry Andric CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext()); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric bool InStaticMethod = Method && Method->isStatic(); 2405f757f3fSDimitry Andric bool InExplicitObjectMethod = 2415f757f3fSDimitry Andric Method && Method->isExplicitObjectMemberFunction(); 2420b57cec5SDimitry Andric bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep); 2430b57cec5SDimitry Andric 2445f757f3fSDimitry Andric std::string Replacement; 2455f757f3fSDimitry Andric if (InExplicitObjectMethod) { 2465f757f3fSDimitry Andric DeclarationName N = Method->getParamDecl(0)->getDeclName(); 2475f757f3fSDimitry Andric if (!N.isEmpty()) { 2485f757f3fSDimitry Andric Replacement.append(N.getAsString()); 2495f757f3fSDimitry Andric Replacement.append("."); 2505f757f3fSDimitry Andric } 2515f757f3fSDimitry Andric } 2520b57cec5SDimitry Andric if (IsField && InStaticMethod) 2530b57cec5SDimitry Andric // "invalid use of member 'x' in static member function" 2545f757f3fSDimitry Andric SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method) 2555f757f3fSDimitry Andric << Range << nameInfo.getName() << /*static*/ 0; 2565f757f3fSDimitry Andric else if (IsField && InExplicitObjectMethod) { 2575f757f3fSDimitry Andric auto Diag = SemaRef.Diag(Loc, diag::err_invalid_member_use_in_method) 2585f757f3fSDimitry Andric << Range << nameInfo.getName() << /*explicit*/ 1; 2595f757f3fSDimitry Andric if (!Replacement.empty()) 2605f757f3fSDimitry Andric Diag << FixItHint::CreateInsertion(Loc, Replacement); 2615f757f3fSDimitry Andric } else if (ContextClass && RepClass && SS.isEmpty() && 2625f757f3fSDimitry Andric !InExplicitObjectMethod && !InStaticMethod && 2635f757f3fSDimitry Andric !RepClass->Equals(ContextClass) && 2645f757f3fSDimitry Andric RepClass->Encloses(ContextClass)) 2650b57cec5SDimitry Andric // Unqualified lookup in a non-static member function found a member of an 2660b57cec5SDimitry Andric // enclosing class. 2670b57cec5SDimitry Andric SemaRef.Diag(Loc, diag::err_nested_non_static_member_use) 2680b57cec5SDimitry Andric << IsField << RepClass << nameInfo.getName() << ContextClass << Range; 2690b57cec5SDimitry Andric else if (IsField) 2700b57cec5SDimitry Andric SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use) 2710b57cec5SDimitry Andric << nameInfo.getName() << Range; 2725f757f3fSDimitry Andric else if (!InExplicitObjectMethod) 2730b57cec5SDimitry Andric SemaRef.Diag(Loc, diag::err_member_call_without_object) 2745f757f3fSDimitry Andric << Range << /*static*/ 0; 2755f757f3fSDimitry Andric else { 276cb14a3feSDimitry Andric if (const auto *Tpl = dyn_cast<FunctionTemplateDecl>(Rep)) 277cb14a3feSDimitry Andric Rep = Tpl->getTemplatedDecl(); 278cb14a3feSDimitry Andric const auto *Callee = cast<CXXMethodDecl>(Rep); 2795f757f3fSDimitry Andric auto Diag = SemaRef.Diag(Loc, diag::err_member_call_without_object) 2805f757f3fSDimitry Andric << Range << Callee->isExplicitObjectMemberFunction(); 2815f757f3fSDimitry Andric if (!Replacement.empty()) 2825f757f3fSDimitry Andric Diag << FixItHint::CreateInsertion(Loc, Replacement); 2835f757f3fSDimitry Andric } 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860fca6ea1SDimitry Andric bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, 2870fca6ea1SDimitry Andric LookupResult &R, 2880fca6ea1SDimitry Andric bool IsAddressOfOperand) { 2890fca6ea1SDimitry Andric if (!getLangOpts().CPlusPlus) 2900fca6ea1SDimitry Andric return false; 2910fca6ea1SDimitry Andric else if (R.empty() || !R.begin()->isCXXClassMember()) 2920fca6ea1SDimitry Andric return false; 2930fca6ea1SDimitry Andric else if (!IsAddressOfOperand) 2940fca6ea1SDimitry Andric return true; 2950fca6ea1SDimitry Andric else if (!SS.isEmpty()) 2960fca6ea1SDimitry Andric return false; 2970fca6ea1SDimitry Andric else if (R.isOverloadedResult()) 2980fca6ea1SDimitry Andric return false; 2990fca6ea1SDimitry Andric else if (R.isUnresolvableResult()) 3000fca6ea1SDimitry Andric return true; 3010fca6ea1SDimitry Andric else 3020fca6ea1SDimitry Andric return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl()); 3030fca6ea1SDimitry Andric } 3040fca6ea1SDimitry Andric 305e8d8bef9SDimitry Andric ExprResult Sema::BuildPossibleImplicitMemberExpr( 306e8d8bef9SDimitry Andric const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, 3070fca6ea1SDimitry Andric const TemplateArgumentListInfo *TemplateArgs, const Scope *S) { 3080fca6ea1SDimitry Andric switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) { 3090b57cec5SDimitry Andric case IMA_Instance: 3100b57cec5SDimitry Andric case IMA_Mixed: 3110b57cec5SDimitry Andric case IMA_Mixed_Unrelated: 3120b57cec5SDimitry Andric case IMA_Unresolved: 3130fca6ea1SDimitry Andric return BuildImplicitMemberExpr( 3140fca6ea1SDimitry Andric SS, TemplateKWLoc, R, TemplateArgs, 3150fca6ea1SDimitry Andric /*IsKnownInstance=*/Classification == IMA_Instance, S); 3160b57cec5SDimitry Andric case IMA_Field_Uneval_Context: 3170b57cec5SDimitry Andric Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) 3180b57cec5SDimitry Andric << R.getLookupNameInfo().getName(); 319bdd1243dSDimitry Andric [[fallthrough]]; 3200b57cec5SDimitry Andric case IMA_Static: 3210b57cec5SDimitry Andric case IMA_Abstract: 3225f757f3fSDimitry Andric case IMA_Mixed_StaticOrExplicitContext: 3235f757f3fSDimitry Andric case IMA_Unresolved_StaticOrExplicitContext: 3240b57cec5SDimitry Andric if (TemplateArgs || TemplateKWLoc.isValid()) 3250fca6ea1SDimitry Andric return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false, 3260fca6ea1SDimitry Andric TemplateArgs); 3270fca6ea1SDimitry Andric return BuildDeclarationNameExpr(SS, R, /*NeedsADL=*/false, 3280fca6ea1SDimitry Andric /*AcceptInvalidDecl=*/false); 3290fca6ea1SDimitry Andric case IMA_Dependent: 3300fca6ea1SDimitry Andric R.suppressDiagnostics(); 3310fca6ea1SDimitry Andric return UnresolvedLookupExpr::Create( 3320fca6ea1SDimitry Andric Context, R.getNamingClass(), SS.getWithLocInContext(Context), 3330fca6ea1SDimitry Andric TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false, 334*62987288SDimitry Andric TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true, 335*62987288SDimitry Andric /*KnownInstantiationDependent=*/true); 3360b57cec5SDimitry Andric 3375f757f3fSDimitry Andric case IMA_Error_StaticOrExplicitContext: 3380b57cec5SDimitry Andric case IMA_Error_Unrelated: 3390b57cec5SDimitry Andric diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), 3400b57cec5SDimitry Andric R.getLookupNameInfo()); 3410b57cec5SDimitry Andric return ExprError(); 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric llvm_unreachable("unexpected instance member access kind"); 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric /// Determine whether input char is from rgba component set. 3480b57cec5SDimitry Andric static bool 3490b57cec5SDimitry Andric IsRGBA(char c) { 3500b57cec5SDimitry Andric switch (c) { 3510b57cec5SDimitry Andric case 'r': 3520b57cec5SDimitry Andric case 'g': 3530b57cec5SDimitry Andric case 'b': 3540b57cec5SDimitry Andric case 'a': 3550b57cec5SDimitry Andric return true; 3560b57cec5SDimitry Andric default: 3570b57cec5SDimitry Andric return false; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric // OpenCL v1.1, s6.1.7 3620b57cec5SDimitry Andric // The component swizzle length must be in accordance with the acceptable 3630b57cec5SDimitry Andric // vector sizes. 3640b57cec5SDimitry Andric static bool IsValidOpenCLComponentSwizzleLength(unsigned len) 3650b57cec5SDimitry Andric { 3660b57cec5SDimitry Andric return (len >= 1 && len <= 4) || len == 8 || len == 16; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric /// Check an ext-vector component access expression. 3700b57cec5SDimitry Andric /// 3710b57cec5SDimitry Andric /// VK should be set in advance to the value kind of the base 3720b57cec5SDimitry Andric /// expression. 3730b57cec5SDimitry Andric static QualType 3740b57cec5SDimitry Andric CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK, 3750b57cec5SDimitry Andric SourceLocation OpLoc, const IdentifierInfo *CompName, 3760b57cec5SDimitry Andric SourceLocation CompLoc) { 3770b57cec5SDimitry Andric // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements, 3780b57cec5SDimitry Andric // see FIXME there. 3790b57cec5SDimitry Andric // 3800b57cec5SDimitry Andric // FIXME: This logic can be greatly simplified by splitting it along 3810b57cec5SDimitry Andric // halving/not halving and reworking the component checking. 3820b57cec5SDimitry Andric const ExtVectorType *vecType = baseType->getAs<ExtVectorType>(); 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric // The vector accessor can't exceed the number of elements. 3850b57cec5SDimitry Andric const char *compStr = CompName->getNameStart(); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric // This flag determines whether or not the component is one of the four 3880b57cec5SDimitry Andric // special names that indicate a subset of exactly half the elements are 3890b57cec5SDimitry Andric // to be selected. 3900b57cec5SDimitry Andric bool HalvingSwizzle = false; 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric // This flag determines whether or not CompName has an 's' char prefix, 3930b57cec5SDimitry Andric // indicating that it is a string of hex values to be used as vector indices. 3940b57cec5SDimitry Andric bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1]; 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric bool HasRepeated = false; 3970b57cec5SDimitry Andric bool HasIndex[16] = {}; 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric int Idx; 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric // Check that we've found one of the special components, or that the component 4020b57cec5SDimitry Andric // names must come from the same set. 4030b57cec5SDimitry Andric if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") || 4040b57cec5SDimitry Andric !strcmp(compStr, "even") || !strcmp(compStr, "odd")) { 4050b57cec5SDimitry Andric HalvingSwizzle = true; 4060b57cec5SDimitry Andric } else if (!HexSwizzle && 4070b57cec5SDimitry Andric (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) { 4080b57cec5SDimitry Andric bool HasRGBA = IsRGBA(*compStr); 4090b57cec5SDimitry Andric do { 4100b57cec5SDimitry Andric // Ensure that xyzw and rgba components don't intermingle. 4110b57cec5SDimitry Andric if (HasRGBA != IsRGBA(*compStr)) 4120b57cec5SDimitry Andric break; 4130b57cec5SDimitry Andric if (HasIndex[Idx]) HasRepeated = true; 4140b57cec5SDimitry Andric HasIndex[Idx] = true; 4150b57cec5SDimitry Andric compStr++; 4160b57cec5SDimitry Andric } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1); 4170b57cec5SDimitry Andric 418fe6060f1SDimitry Andric // Emit a warning if an rgba selector is used earlier than OpenCL C 3.0. 4190b57cec5SDimitry Andric if (HasRGBA || (*compStr && IsRGBA(*compStr))) { 420349cc55cSDimitry Andric if (S.getLangOpts().OpenCL && 421349cc55cSDimitry Andric S.getLangOpts().getOpenCLCompatibleVersion() < 300) { 4220b57cec5SDimitry Andric const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr; 4230b57cec5SDimitry Andric S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector) 424fe6060f1SDimitry Andric << StringRef(DiagBegin, 1) << SourceRange(CompLoc); 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric } else { 4280b57cec5SDimitry Andric if (HexSwizzle) compStr++; 4290b57cec5SDimitry Andric while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) { 4300b57cec5SDimitry Andric if (HasIndex[Idx]) HasRepeated = true; 4310b57cec5SDimitry Andric HasIndex[Idx] = true; 4320b57cec5SDimitry Andric compStr++; 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric if (!HalvingSwizzle && *compStr) { 4370b57cec5SDimitry Andric // We didn't get to the end of the string. This means the component names 4380b57cec5SDimitry Andric // didn't come from the same set *or* we encountered an illegal name. 4390b57cec5SDimitry Andric S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal) 4400b57cec5SDimitry Andric << StringRef(compStr, 1) << SourceRange(CompLoc); 4410b57cec5SDimitry Andric return QualType(); 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric // Ensure no component accessor exceeds the width of the vector type it 4450b57cec5SDimitry Andric // operates on. 4460b57cec5SDimitry Andric if (!HalvingSwizzle) { 4470b57cec5SDimitry Andric compStr = CompName->getNameStart(); 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric if (HexSwizzle) 4500b57cec5SDimitry Andric compStr++; 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric while (*compStr) { 4530b57cec5SDimitry Andric if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) { 4540b57cec5SDimitry Andric S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length) 4550b57cec5SDimitry Andric << baseType << SourceRange(CompLoc); 4560b57cec5SDimitry Andric return QualType(); 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric // OpenCL mode requires swizzle length to be in accordance with accepted 4620b57cec5SDimitry Andric // sizes. Clang however supports arbitrary lengths for other languages. 4630b57cec5SDimitry Andric if (S.getLangOpts().OpenCL && !HalvingSwizzle) { 4640b57cec5SDimitry Andric unsigned SwizzleLength = CompName->getLength(); 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric if (HexSwizzle) 4670b57cec5SDimitry Andric SwizzleLength--; 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric if (IsValidOpenCLComponentSwizzleLength(SwizzleLength) == false) { 4700b57cec5SDimitry Andric S.Diag(OpLoc, diag::err_opencl_ext_vector_component_invalid_length) 4710b57cec5SDimitry Andric << SwizzleLength << SourceRange(CompLoc); 4720b57cec5SDimitry Andric return QualType(); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric // The component accessor looks fine - now we need to compute the actual type. 4770b57cec5SDimitry Andric // The vector type is implied by the component accessor. For example, 4780b57cec5SDimitry Andric // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc. 4790b57cec5SDimitry Andric // vec4.s0 is a float, vec4.s23 is a vec3, etc. 4800b57cec5SDimitry Andric // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2. 4810b57cec5SDimitry Andric unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2 4820b57cec5SDimitry Andric : CompName->getLength(); 4830b57cec5SDimitry Andric if (HexSwizzle) 4840b57cec5SDimitry Andric CompSize--; 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric if (CompSize == 1) 4870b57cec5SDimitry Andric return vecType->getElementType(); 4880b57cec5SDimitry Andric 489fe6060f1SDimitry Andric if (HasRepeated) 490fe6060f1SDimitry Andric VK = VK_PRValue; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize); 4930b57cec5SDimitry Andric // Now look up the TypeDefDecl from the vector type. Without this, 4940b57cec5SDimitry Andric // diagostics look bad. We want extended vector types to appear built-in. 4950b57cec5SDimitry Andric for (Sema::ExtVectorDeclsType::iterator 4960b57cec5SDimitry Andric I = S.ExtVectorDecls.begin(S.getExternalSource()), 4970b57cec5SDimitry Andric E = S.ExtVectorDecls.end(); 4980b57cec5SDimitry Andric I != E; ++I) { 4990b57cec5SDimitry Andric if ((*I)->getUnderlyingType() == VT) 5000b57cec5SDimitry Andric return S.Context.getTypedefType(*I); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric return VT; // should never get here (a typedef type should always be found). 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, 5070b57cec5SDimitry Andric IdentifierInfo *Member, 5080b57cec5SDimitry Andric const Selector &Sel, 5090b57cec5SDimitry Andric ASTContext &Context) { 5100b57cec5SDimitry Andric if (Member) 5110b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration( 5120b57cec5SDimitry Andric Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) 5130b57cec5SDimitry Andric return PD; 5140b57cec5SDimitry Andric if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) 5150b57cec5SDimitry Andric return OMD; 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric for (const auto *I : PDecl->protocols()) { 5180b57cec5SDimitry Andric if (Decl *D = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, 5190b57cec5SDimitry Andric Context)) 5200b57cec5SDimitry Andric return D; 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric return nullptr; 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy, 5260b57cec5SDimitry Andric IdentifierInfo *Member, 5270b57cec5SDimitry Andric const Selector &Sel, 5280b57cec5SDimitry Andric ASTContext &Context) { 5290b57cec5SDimitry Andric // Check protocols on qualified interfaces. 5300b57cec5SDimitry Andric Decl *GDecl = nullptr; 5310b57cec5SDimitry Andric for (const auto *I : QIdTy->quals()) { 5320b57cec5SDimitry Andric if (Member) 5330b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration( 5340b57cec5SDimitry Andric Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { 5350b57cec5SDimitry Andric GDecl = PD; 5360b57cec5SDimitry Andric break; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric // Also must look for a getter or setter name which uses property syntax. 5390b57cec5SDimitry Andric if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) { 5400b57cec5SDimitry Andric GDecl = OMD; 5410b57cec5SDimitry Andric break; 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric if (!GDecl) { 5450b57cec5SDimitry Andric for (const auto *I : QIdTy->quals()) { 5460b57cec5SDimitry Andric // Search in the protocol-qualifier list of current protocol. 5470b57cec5SDimitry Andric GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context); 5480b57cec5SDimitry Andric if (GDecl) 5490b57cec5SDimitry Andric return GDecl; 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric return GDecl; 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric ExprResult 5560b57cec5SDimitry Andric Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, 5570b57cec5SDimitry Andric bool IsArrow, SourceLocation OpLoc, 5580b57cec5SDimitry Andric const CXXScopeSpec &SS, 5590b57cec5SDimitry Andric SourceLocation TemplateKWLoc, 5600b57cec5SDimitry Andric NamedDecl *FirstQualifierInScope, 5610b57cec5SDimitry Andric const DeclarationNameInfo &NameInfo, 5620b57cec5SDimitry Andric const TemplateArgumentListInfo *TemplateArgs) { 5630b57cec5SDimitry Andric // Even in dependent contexts, try to diagnose base expressions with 5640b57cec5SDimitry Andric // obviously wrong types, e.g.: 5650b57cec5SDimitry Andric // 5660b57cec5SDimitry Andric // T* t; 5670b57cec5SDimitry Andric // t.f; 5680b57cec5SDimitry Andric // 5690b57cec5SDimitry Andric // In Obj-C++, however, the above expression is valid, since it could be 5700b57cec5SDimitry Andric // accessing the 'f' property if T is an Obj-C interface. The extra check 5710b57cec5SDimitry Andric // allows this, while still reporting an error if T is a struct pointer. 5720b57cec5SDimitry Andric if (!IsArrow) { 5730b57cec5SDimitry Andric const PointerType *PT = BaseType->getAs<PointerType>(); 5740b57cec5SDimitry Andric if (PT && (!getLangOpts().ObjC || 5750b57cec5SDimitry Andric PT->getPointeeType()->isRecordType())) { 5760b57cec5SDimitry Andric assert(BaseExpr && "cannot happen with implicit member accesses"); 5770b57cec5SDimitry Andric Diag(OpLoc, diag::err_typecheck_member_reference_struct_union) 5780b57cec5SDimitry Andric << BaseType << BaseExpr->getSourceRange() << NameInfo.getSourceRange(); 5790b57cec5SDimitry Andric return ExprError(); 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 58304eeddc0SDimitry Andric assert(BaseType->isDependentType() || NameInfo.getName().isDependentName() || 58404eeddc0SDimitry Andric isDependentScopeSpecifier(SS) || 58504eeddc0SDimitry Andric (TemplateArgs && llvm::any_of(TemplateArgs->arguments(), 58604eeddc0SDimitry Andric [](const TemplateArgumentLoc &Arg) { 58704eeddc0SDimitry Andric return Arg.getArgument().isDependent(); 58804eeddc0SDimitry Andric }))); 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr 5910b57cec5SDimitry Andric // must have pointer type, and the accessed type is the pointee. 5920b57cec5SDimitry Andric return CXXDependentScopeMemberExpr::Create( 5930b57cec5SDimitry Andric Context, BaseExpr, BaseType, IsArrow, OpLoc, 5940b57cec5SDimitry Andric SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope, 5950b57cec5SDimitry Andric NameInfo, TemplateArgs); 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric /// We know that the given qualified member reference points only to 5990b57cec5SDimitry Andric /// declarations which do not belong to the static type of the base 6000b57cec5SDimitry Andric /// expression. Diagnose the problem. 6010b57cec5SDimitry Andric static void DiagnoseQualifiedMemberReference(Sema &SemaRef, 6020b57cec5SDimitry Andric Expr *BaseExpr, 6030b57cec5SDimitry Andric QualType BaseType, 6040b57cec5SDimitry Andric const CXXScopeSpec &SS, 6050b57cec5SDimitry Andric NamedDecl *rep, 6060b57cec5SDimitry Andric const DeclarationNameInfo &nameInfo) { 6070b57cec5SDimitry Andric // If this is an implicit member access, use a different set of 6080b57cec5SDimitry Andric // diagnostics. 6090b57cec5SDimitry Andric if (!BaseExpr) 6100b57cec5SDimitry Andric return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo); 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated) 6130b57cec5SDimitry Andric << SS.getRange() << rep << BaseType; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, 6170b57cec5SDimitry Andric QualType BaseType, 6180b57cec5SDimitry Andric const CXXScopeSpec &SS, 6190b57cec5SDimitry Andric const LookupResult &R) { 6200b57cec5SDimitry Andric CXXRecordDecl *BaseRecord = 6210b57cec5SDimitry Andric cast_or_null<CXXRecordDecl>(computeDeclContext(BaseType)); 6220b57cec5SDimitry Andric if (!BaseRecord) { 6230b57cec5SDimitry Andric // We can't check this yet because the base type is still 6240b57cec5SDimitry Andric // dependent. 6250b57cec5SDimitry Andric assert(BaseType->isDependentType()); 6260b57cec5SDimitry Andric return false; 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { 6300b57cec5SDimitry Andric // If this is an implicit member reference and we find a 6310b57cec5SDimitry Andric // non-instance member, it's not an error. 6320b57cec5SDimitry Andric if (!BaseExpr && !(*I)->isCXXInstanceMember()) 6330b57cec5SDimitry Andric return false; 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric // Note that we use the DC of the decl, not the underlying decl. 636349cc55cSDimitry Andric DeclContext *DC = (*I)->getDeclContext()->getNonTransparentContext(); 6370b57cec5SDimitry Andric if (!DC->isRecord()) 6380b57cec5SDimitry Andric continue; 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); 6410b57cec5SDimitry Andric if (BaseRecord->getCanonicalDecl() == MemberRecord || 6420b57cec5SDimitry Andric !BaseRecord->isProvablyNotDerivedFrom(MemberRecord)) 6430b57cec5SDimitry Andric return false; 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS, 6470b57cec5SDimitry Andric R.getRepresentativeDecl(), 6480b57cec5SDimitry Andric R.getLookupNameInfo()); 6490b57cec5SDimitry Andric return true; 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric namespace { 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric // Callback to only accept typo corrections that are either a ValueDecl or a 6550b57cec5SDimitry Andric // FunctionTemplateDecl and are declared in the current record or, for a C++ 6560b57cec5SDimitry Andric // classes, one of its base classes. 6570b57cec5SDimitry Andric class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback { 6580b57cec5SDimitry Andric public: 6590fca6ea1SDimitry Andric explicit RecordMemberExprValidatorCCC(QualType RTy) 6600fca6ea1SDimitry Andric : Record(RTy->getAsRecordDecl()) { 6610b57cec5SDimitry Andric // Don't add bare keywords to the consumer since they will always fail 6620b57cec5SDimitry Andric // validation by virtue of not being associated with any decls. 6630b57cec5SDimitry Andric WantTypeSpecifiers = false; 6640b57cec5SDimitry Andric WantExpressionKeywords = false; 6650b57cec5SDimitry Andric WantCXXNamedCasts = false; 6660b57cec5SDimitry Andric WantFunctionLikeCasts = false; 6670b57cec5SDimitry Andric WantRemainingKeywords = false; 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric bool ValidateCandidate(const TypoCorrection &candidate) override { 6710b57cec5SDimitry Andric NamedDecl *ND = candidate.getCorrectionDecl(); 6720b57cec5SDimitry Andric // Don't accept candidates that cannot be member functions, constants, 6730b57cec5SDimitry Andric // variables, or templates. 6740b57cec5SDimitry Andric if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) 6750b57cec5SDimitry Andric return false; 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // Accept candidates that occur in the current record. 6780b57cec5SDimitry Andric if (Record->containsDecl(ND)) 6790b57cec5SDimitry Andric return true; 6800b57cec5SDimitry Andric 681349cc55cSDimitry Andric if (const auto *RD = dyn_cast<CXXRecordDecl>(Record)) { 6820b57cec5SDimitry Andric // Accept candidates that occur in any of the current class' base classes. 6830b57cec5SDimitry Andric for (const auto &BS : RD->bases()) { 684349cc55cSDimitry Andric if (const auto *BSTy = BS.getType()->getAs<RecordType>()) { 6850b57cec5SDimitry Andric if (BSTy->getDecl()->containsDecl(ND)) 6860b57cec5SDimitry Andric return true; 6870b57cec5SDimitry Andric } 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric return false; 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric std::unique_ptr<CorrectionCandidateCallback> clone() override { 695a7dea167SDimitry Andric return std::make_unique<RecordMemberExprValidatorCCC>(*this); 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric private: 6990b57cec5SDimitry Andric const RecordDecl *const Record; 7000b57cec5SDimitry Andric }; 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, 7050fca6ea1SDimitry Andric Expr *BaseExpr, QualType RTy, 7060b57cec5SDimitry Andric SourceLocation OpLoc, bool IsArrow, 7070b57cec5SDimitry Andric CXXScopeSpec &SS, bool HasTemplateArgs, 7080b57cec5SDimitry Andric SourceLocation TemplateKWLoc, 7090b57cec5SDimitry Andric TypoExpr *&TE) { 7100b57cec5SDimitry Andric SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange(); 7110fca6ea1SDimitry Andric if (!RTy->isDependentType() && 7120fca6ea1SDimitry Andric !SemaRef.isThisOutsideMemberFunctionBody(RTy) && 7130fca6ea1SDimitry Andric SemaRef.RequireCompleteType( 7140fca6ea1SDimitry Andric OpLoc, RTy, diag::err_typecheck_incomplete_tag, BaseRange)) 7150b57cec5SDimitry Andric return true; 7160b57cec5SDimitry Andric 7170fca6ea1SDimitry Andric // LookupTemplateName/LookupParsedName don't expect these both to exist 7180fca6ea1SDimitry Andric // simultaneously. 7190fca6ea1SDimitry Andric QualType ObjectType = SS.isSet() ? QualType() : RTy; 7200fca6ea1SDimitry Andric if (HasTemplateArgs || TemplateKWLoc.isValid()) 7210fca6ea1SDimitry Andric return SemaRef.LookupTemplateName(R, 7220fca6ea1SDimitry Andric /*S=*/nullptr, SS, ObjectType, 7230fca6ea1SDimitry Andric /*EnteringContext=*/false, TemplateKWLoc); 7240b57cec5SDimitry Andric 7250fca6ea1SDimitry Andric SemaRef.LookupParsedName(R, /*S=*/nullptr, &SS, ObjectType); 7260b57cec5SDimitry Andric 7270fca6ea1SDimitry Andric if (!R.empty() || R.wasNotFoundInCurrentInstantiation()) 7280b57cec5SDimitry Andric return false; 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric DeclarationName Typo = R.getLookupName(); 7310b57cec5SDimitry Andric SourceLocation TypoLoc = R.getNameLoc(); 7320fca6ea1SDimitry Andric // Recompute the lookup context. 7330fca6ea1SDimitry Andric DeclContext *DC = SS.isSet() ? SemaRef.computeDeclContext(SS) 7340fca6ea1SDimitry Andric : SemaRef.computeDeclContext(RTy); 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric struct QueryState { 7370b57cec5SDimitry Andric Sema &SemaRef; 7380b57cec5SDimitry Andric DeclarationNameInfo NameInfo; 7390b57cec5SDimitry Andric Sema::LookupNameKind LookupKind; 7400fca6ea1SDimitry Andric RedeclarationKind Redecl; 7410b57cec5SDimitry Andric }; 7420b57cec5SDimitry Andric QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(), 7430b57cec5SDimitry Andric R.redeclarationKind()}; 7440b57cec5SDimitry Andric RecordMemberExprValidatorCCC CCC(RTy); 7450b57cec5SDimitry Andric TE = SemaRef.CorrectTypoDelayed( 7460b57cec5SDimitry Andric R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC, 7470b57cec5SDimitry Andric [=, &SemaRef](const TypoCorrection &TC) { 7480b57cec5SDimitry Andric if (TC) { 7490b57cec5SDimitry Andric assert(!TC.isKeyword() && 7500b57cec5SDimitry Andric "Got a keyword as a correction for a member!"); 7510b57cec5SDimitry Andric bool DroppedSpecifier = 7520b57cec5SDimitry Andric TC.WillReplaceSpecifier() && 7530b57cec5SDimitry Andric Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts()); 7540b57cec5SDimitry Andric SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest) 7550b57cec5SDimitry Andric << Typo << DC << DroppedSpecifier 7560b57cec5SDimitry Andric << SS.getRange()); 7570b57cec5SDimitry Andric } else { 7580fca6ea1SDimitry Andric SemaRef.Diag(TypoLoc, diag::err_no_member) 7590fca6ea1SDimitry Andric << Typo << DC << (SS.isSet() ? SS.getRange() : BaseRange); 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric }, 7620b57cec5SDimitry Andric [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable { 7630b57cec5SDimitry Andric LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl); 7640b57cec5SDimitry Andric R.clear(); // Ensure there's no decls lingering in the shared state. 7650b57cec5SDimitry Andric R.suppressDiagnostics(); 7660b57cec5SDimitry Andric R.setLookupName(TC.getCorrection()); 7670b57cec5SDimitry Andric for (NamedDecl *ND : TC) 7680b57cec5SDimitry Andric R.addDecl(ND); 7690b57cec5SDimitry Andric R.resolveKind(); 7700b57cec5SDimitry Andric return SemaRef.BuildMemberReferenceExpr( 7710b57cec5SDimitry Andric BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(), 7720b57cec5SDimitry Andric nullptr, R, nullptr, nullptr); 7730b57cec5SDimitry Andric }, 7740b57cec5SDimitry Andric Sema::CTK_ErrorRecovery, DC); 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric return false; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, 7800b57cec5SDimitry Andric ExprResult &BaseExpr, bool &IsArrow, 7810b57cec5SDimitry Andric SourceLocation OpLoc, CXXScopeSpec &SS, 7820b57cec5SDimitry Andric Decl *ObjCImpDecl, bool HasTemplateArgs, 7830b57cec5SDimitry Andric SourceLocation TemplateKWLoc); 7840b57cec5SDimitry Andric 7850fca6ea1SDimitry Andric ExprResult Sema::BuildMemberReferenceExpr( 7860fca6ea1SDimitry Andric Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, 7870fca6ea1SDimitry Andric CXXScopeSpec &SS, SourceLocation TemplateKWLoc, 7880fca6ea1SDimitry Andric NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, 7890fca6ea1SDimitry Andric const TemplateArgumentListInfo *TemplateArgs, const Scope *S, 7900b57cec5SDimitry Andric ActOnMemberAccessExtraArgs *ExtraArgs) { 7910b57cec5SDimitry Andric LookupResult R(*this, NameInfo, LookupMemberName); 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric // Implicit member accesses. 7940b57cec5SDimitry Andric if (!Base) { 7950b57cec5SDimitry Andric TypoExpr *TE = nullptr; 7960b57cec5SDimitry Andric QualType RecordTy = BaseType; 797fe6060f1SDimitry Andric if (IsArrow) RecordTy = RecordTy->castAs<PointerType>()->getPointeeType(); 7980fca6ea1SDimitry Andric if (LookupMemberExprInRecord(*this, R, nullptr, RecordTy, OpLoc, IsArrow, 7990fca6ea1SDimitry Andric SS, TemplateArgs != nullptr, TemplateKWLoc, 8000fca6ea1SDimitry Andric TE)) 8010b57cec5SDimitry Andric return ExprError(); 8020b57cec5SDimitry Andric if (TE) 8030b57cec5SDimitry Andric return TE; 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric // Explicit member accesses. 8060b57cec5SDimitry Andric } else { 8070b57cec5SDimitry Andric ExprResult BaseResult = Base; 8080b57cec5SDimitry Andric ExprResult Result = 8090b57cec5SDimitry Andric LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS, 8100b57cec5SDimitry Andric ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr, 8110b57cec5SDimitry Andric TemplateArgs != nullptr, TemplateKWLoc); 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric if (BaseResult.isInvalid()) 8140b57cec5SDimitry Andric return ExprError(); 8150b57cec5SDimitry Andric Base = BaseResult.get(); 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric if (Result.isInvalid()) 8180b57cec5SDimitry Andric return ExprError(); 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric if (Result.get()) 8210b57cec5SDimitry Andric return Result; 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric // LookupMemberExpr can modify Base, and thus change BaseType 8240b57cec5SDimitry Andric BaseType = Base->getType(); 8250b57cec5SDimitry Andric } 8260b57cec5SDimitry Andric 8270fca6ea1SDimitry Andric // BuildMemberReferenceExpr expects the nested-name-specifier, if any, to be 8280fca6ea1SDimitry Andric // valid. 8290fca6ea1SDimitry Andric if (SS.isInvalid()) 8300fca6ea1SDimitry Andric return ExprError(); 8310fca6ea1SDimitry Andric 8320b57cec5SDimitry Andric return BuildMemberReferenceExpr(Base, BaseType, 8330b57cec5SDimitry Andric OpLoc, IsArrow, SS, TemplateKWLoc, 8340b57cec5SDimitry Andric FirstQualifierInScope, R, TemplateArgs, S, 8350b57cec5SDimitry Andric false, ExtraArgs); 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric ExprResult 8390b57cec5SDimitry Andric Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, 8400b57cec5SDimitry Andric SourceLocation loc, 8410b57cec5SDimitry Andric IndirectFieldDecl *indirectField, 8420b57cec5SDimitry Andric DeclAccessPair foundDecl, 8430b57cec5SDimitry Andric Expr *baseObjectExpr, 8440b57cec5SDimitry Andric SourceLocation opLoc) { 8450b57cec5SDimitry Andric // First, build the expression that refers to the base object. 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric // Case 1: the base of the indirect field is not a field. 8480b57cec5SDimitry Andric VarDecl *baseVariable = indirectField->getVarDecl(); 8490b57cec5SDimitry Andric CXXScopeSpec EmptySS; 8500b57cec5SDimitry Andric if (baseVariable) { 8510b57cec5SDimitry Andric assert(baseVariable->getType()->isRecordType()); 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric // In principle we could have a member access expression that 8540b57cec5SDimitry Andric // accesses an anonymous struct/union that's a static member of 8550b57cec5SDimitry Andric // the base object's class. However, under the current standard, 8560b57cec5SDimitry Andric // static data members cannot be anonymous structs or unions. 8570b57cec5SDimitry Andric // Supporting this is as easy as building a MemberExpr here. 8580b57cec5SDimitry Andric assert(!baseObjectExpr && "anonymous struct/union is static data member?"); 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric DeclarationNameInfo baseNameInfo(DeclarationName(), loc); 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric ExprResult result 8630b57cec5SDimitry Andric = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable); 8640b57cec5SDimitry Andric if (result.isInvalid()) return ExprError(); 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric baseObjectExpr = result.get(); 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric assert((baseVariable || baseObjectExpr) && 8700b57cec5SDimitry Andric "referencing anonymous struct/union without a base variable or " 8710b57cec5SDimitry Andric "expression"); 8720b57cec5SDimitry Andric 8730b57cec5SDimitry Andric // Build the implicit member references to the field of the 8740b57cec5SDimitry Andric // anonymous struct/union. 8750b57cec5SDimitry Andric Expr *result = baseObjectExpr; 8760b57cec5SDimitry Andric IndirectFieldDecl::chain_iterator 8770b57cec5SDimitry Andric FI = indirectField->chain_begin(), FEnd = indirectField->chain_end(); 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric // Case 2: the base of the indirect field is a field and the user 8800b57cec5SDimitry Andric // wrote a member expression. 8810b57cec5SDimitry Andric if (!baseVariable) { 8820b57cec5SDimitry Andric FieldDecl *field = cast<FieldDecl>(*FI); 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType(); 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric // Make a nameInfo that properly uses the anonymous name. 8870b57cec5SDimitry Andric DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric // Build the first member access in the chain with full information. 8900b57cec5SDimitry Andric result = 8910b57cec5SDimitry Andric BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(), 8920b57cec5SDimitry Andric SS, field, foundDecl, memberNameInfo) 8930b57cec5SDimitry Andric .get(); 8940b57cec5SDimitry Andric if (!result) 8950b57cec5SDimitry Andric return ExprError(); 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric // In all cases, we should now skip the first declaration in the chain. 8990b57cec5SDimitry Andric ++FI; 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric while (FI != FEnd) { 9020b57cec5SDimitry Andric FieldDecl *field = cast<FieldDecl>(*FI++); 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric // FIXME: these are somewhat meaningless 9050b57cec5SDimitry Andric DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); 9060b57cec5SDimitry Andric DeclAccessPair fakeFoundDecl = 9070b57cec5SDimitry Andric DeclAccessPair::make(field, field->getAccess()); 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric result = 9100b57cec5SDimitry Andric BuildFieldReferenceExpr(result, /*isarrow*/ false, SourceLocation(), 9110b57cec5SDimitry Andric (FI == FEnd ? SS : EmptySS), field, 9120b57cec5SDimitry Andric fakeFoundDecl, memberNameInfo) 9130b57cec5SDimitry Andric .get(); 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric return result; 9170b57cec5SDimitry Andric } 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric static ExprResult 9200b57cec5SDimitry Andric BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow, 9210b57cec5SDimitry Andric const CXXScopeSpec &SS, 9220b57cec5SDimitry Andric MSPropertyDecl *PD, 9230b57cec5SDimitry Andric const DeclarationNameInfo &NameInfo) { 9240b57cec5SDimitry Andric // Property names are always simple identifiers and therefore never 9250b57cec5SDimitry Andric // require any interesting additional storage. 9260b57cec5SDimitry Andric return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow, 9270b57cec5SDimitry Andric S.Context.PseudoObjectTy, VK_LValue, 9280b57cec5SDimitry Andric SS.getWithLocInContext(S.Context), 9290b57cec5SDimitry Andric NameInfo.getLoc()); 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric MemberExpr *Sema::BuildMemberExpr( 9330b57cec5SDimitry Andric Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, 9340b57cec5SDimitry Andric SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, 9350b57cec5SDimitry Andric bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, 9360b57cec5SDimitry Andric QualType Ty, ExprValueKind VK, ExprObjectKind OK, 9370b57cec5SDimitry Andric const TemplateArgumentListInfo *TemplateArgs) { 938fe6060f1SDimitry Andric assert((!IsArrow || Base->isPRValue()) && 939fe6060f1SDimitry Andric "-> base must be a pointer prvalue"); 9400b57cec5SDimitry Andric MemberExpr *E = 9410b57cec5SDimitry Andric MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, 9420b57cec5SDimitry Andric Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty, 9430b57cec5SDimitry Andric VK, OK, getNonOdrUseReasonInCurrentContext(Member)); 9440b57cec5SDimitry Andric E->setHadMultipleCandidates(HadMultipleCandidates); 9450b57cec5SDimitry Andric MarkMemberReferenced(E); 946480093f4SDimitry Andric 947480093f4SDimitry Andric // C++ [except.spec]p17: 948480093f4SDimitry Andric // An exception-specification is considered to be needed when: 949480093f4SDimitry Andric // - in an expression the function is the unique lookup result or the 950480093f4SDimitry Andric // selected member of a set of overloaded functions 951480093f4SDimitry Andric if (auto *FPT = Ty->getAs<FunctionProtoType>()) { 952480093f4SDimitry Andric if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) { 953480093f4SDimitry Andric if (auto *NewFPT = ResolveExceptionSpec(MemberNameInfo.getLoc(), FPT)) 954480093f4SDimitry Andric E->setType(Context.getQualifiedType(NewFPT, Ty.getQualifiers())); 955480093f4SDimitry Andric } 956480093f4SDimitry Andric } 957480093f4SDimitry Andric 9580b57cec5SDimitry Andric return E; 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric /// Determine if the given scope is within a function-try-block handler. 9620b57cec5SDimitry Andric static bool IsInFnTryBlockHandler(const Scope *S) { 9630b57cec5SDimitry Andric // Walk the scope stack until finding a FnTryCatchScope, or leave the 9640b57cec5SDimitry Andric // function scope. If a FnTryCatchScope is found, check whether the TryScope 9650b57cec5SDimitry Andric // flag is set. If it is not, it's a function-try-block handler. 9660b57cec5SDimitry Andric for (; S != S->getFnParent(); S = S->getParent()) { 96781ad6265SDimitry Andric if (S->isFnTryCatchScope()) 9680b57cec5SDimitry Andric return (S->getFlags() & Scope::TryScope) != Scope::TryScope; 9690b57cec5SDimitry Andric } 9700b57cec5SDimitry Andric return false; 9710b57cec5SDimitry Andric } 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric ExprResult 9740b57cec5SDimitry Andric Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, 9750b57cec5SDimitry Andric SourceLocation OpLoc, bool IsArrow, 9760b57cec5SDimitry Andric const CXXScopeSpec &SS, 9770b57cec5SDimitry Andric SourceLocation TemplateKWLoc, 9780b57cec5SDimitry Andric NamedDecl *FirstQualifierInScope, 9790b57cec5SDimitry Andric LookupResult &R, 9800b57cec5SDimitry Andric const TemplateArgumentListInfo *TemplateArgs, 9810b57cec5SDimitry Andric const Scope *S, 9820b57cec5SDimitry Andric bool SuppressQualifierCheck, 9830b57cec5SDimitry Andric ActOnMemberAccessExtraArgs *ExtraArgs) { 9840fca6ea1SDimitry Andric assert(!SS.isInvalid() && "nested-name-specifier cannot be invalid"); 9850fca6ea1SDimitry Andric // If the member wasn't found in the current instantiation, or if the 9860fca6ea1SDimitry Andric // arrow operator was used with a dependent non-pointer object expression, 9870fca6ea1SDimitry Andric // build a CXXDependentScopeMemberExpr. 9880fca6ea1SDimitry Andric if (R.wasNotFoundInCurrentInstantiation() || 9890fca6ea1SDimitry Andric (R.getLookupName().getCXXOverloadedOperator() == OO_Equal && 9900fca6ea1SDimitry Andric (SS.isSet() ? SS.getScopeRep()->isDependent() 9910fca6ea1SDimitry Andric : BaseExprType->isDependentType()))) 9920fca6ea1SDimitry Andric return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS, 9930fca6ea1SDimitry Andric TemplateKWLoc, FirstQualifierInScope, 9940fca6ea1SDimitry Andric R.getLookupNameInfo(), TemplateArgs); 9950fca6ea1SDimitry Andric 9960b57cec5SDimitry Andric QualType BaseType = BaseExprType; 9970b57cec5SDimitry Andric if (IsArrow) { 9980b57cec5SDimitry Andric assert(BaseType->isPointerType()); 9990b57cec5SDimitry Andric BaseType = BaseType->castAs<PointerType>()->getPointeeType(); 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric R.setBaseObjectType(BaseType); 10020b57cec5SDimitry Andric 10030fca6ea1SDimitry Andric assert((SS.isEmpty() 10040fca6ea1SDimitry Andric ? !BaseType->isDependentType() || computeDeclContext(BaseType) 10050fca6ea1SDimitry Andric : !isDependentScopeSpecifier(SS) || computeDeclContext(SS)) && 10060fca6ea1SDimitry Andric "dependent lookup context that isn't the current instantiation?"); 10070fca6ea1SDimitry Andric 10080b57cec5SDimitry Andric // C++1z [expr.ref]p2: 10090b57cec5SDimitry Andric // For the first option (dot) the first expression shall be a glvalue [...] 1010fe6060f1SDimitry Andric if (!IsArrow && BaseExpr && BaseExpr->isPRValue()) { 10110b57cec5SDimitry Andric ExprResult Converted = TemporaryMaterializationConversion(BaseExpr); 10120b57cec5SDimitry Andric if (Converted.isInvalid()) 10130b57cec5SDimitry Andric return ExprError(); 10140b57cec5SDimitry Andric BaseExpr = Converted.get(); 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); 10180b57cec5SDimitry Andric DeclarationName MemberName = MemberNameInfo.getName(); 10190b57cec5SDimitry Andric SourceLocation MemberLoc = MemberNameInfo.getLoc(); 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric if (R.isAmbiguous()) 10220b57cec5SDimitry Andric return ExprError(); 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric // [except.handle]p10: Referring to any non-static member or base class of an 10250b57cec5SDimitry Andric // object in the handler for a function-try-block of a constructor or 10260b57cec5SDimitry Andric // destructor for that object results in undefined behavior. 10270b57cec5SDimitry Andric const auto *FD = getCurFunctionDecl(); 10280b57cec5SDimitry Andric if (S && BaseExpr && FD && 10290b57cec5SDimitry Andric (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) && 10300b57cec5SDimitry Andric isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) && 10310b57cec5SDimitry Andric IsInFnTryBlockHandler(S)) 10320b57cec5SDimitry Andric Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr) 10330b57cec5SDimitry Andric << isa<CXXDestructorDecl>(FD); 10340b57cec5SDimitry Andric 10350b57cec5SDimitry Andric if (R.empty()) { 10360fca6ea1SDimitry Andric ExprResult RetryExpr = ExprError(); 10370fca6ea1SDimitry Andric if (ExtraArgs && !IsArrow && BaseExpr && !BaseExpr->isTypeDependent()) { 10380b57cec5SDimitry Andric SFINAETrap Trap(*this, true); 10390b57cec5SDimitry Andric ParsedType ObjectType; 10400b57cec5SDimitry Andric bool MayBePseudoDestructor = false; 10410fca6ea1SDimitry Andric RetryExpr = ActOnStartCXXMemberReference(getCurScope(), BaseExpr, OpLoc, 10420fca6ea1SDimitry Andric tok::arrow, ObjectType, 10430b57cec5SDimitry Andric MayBePseudoDestructor); 10440b57cec5SDimitry Andric if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) { 10450b57cec5SDimitry Andric CXXScopeSpec TempSS(SS); 10460b57cec5SDimitry Andric RetryExpr = ActOnMemberAccessExpr( 10470b57cec5SDimitry Andric ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS, 10480b57cec5SDimitry Andric TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl); 10490b57cec5SDimitry Andric } 10500b57cec5SDimitry Andric if (Trap.hasErrorOccurred()) 10510b57cec5SDimitry Andric RetryExpr = ExprError(); 10520b57cec5SDimitry Andric } 10530fca6ea1SDimitry Andric 10540fca6ea1SDimitry Andric // Rederive where we looked up. 10550fca6ea1SDimitry Andric DeclContext *DC = 10560fca6ea1SDimitry Andric (SS.isSet() ? computeDeclContext(SS) : computeDeclContext(BaseType)); 10570fca6ea1SDimitry Andric assert(DC); 10580fca6ea1SDimitry Andric 10590fca6ea1SDimitry Andric if (RetryExpr.isUsable()) 10600b57cec5SDimitry Andric Diag(OpLoc, diag::err_no_member_overloaded_arrow) 10610b57cec5SDimitry Andric << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->"); 10620fca6ea1SDimitry Andric else 10630b57cec5SDimitry Andric Diag(R.getNameLoc(), diag::err_no_member) 10640b57cec5SDimitry Andric << MemberName << DC 10650fca6ea1SDimitry Andric << (SS.isSet() 10660fca6ea1SDimitry Andric ? SS.getRange() 10670fca6ea1SDimitry Andric : (BaseExpr ? BaseExpr->getSourceRange() : SourceRange())); 10680fca6ea1SDimitry Andric return RetryExpr; 10690b57cec5SDimitry Andric } 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric // Diagnose lookups that find only declarations from a non-base 10720b57cec5SDimitry Andric // type. This is possible for either qualified lookups (which may 10730b57cec5SDimitry Andric // have been qualified with an unrelated type) or implicit member 10740b57cec5SDimitry Andric // expressions (which were found with unqualified lookup and thus 10750b57cec5SDimitry Andric // may have come from an enclosing scope). Note that it's okay for 10760b57cec5SDimitry Andric // lookup to find declarations from a non-base type as long as those 10770b57cec5SDimitry Andric // aren't the ones picked by overload resolution. 10780b57cec5SDimitry Andric if ((SS.isSet() || !BaseExpr || 10790b57cec5SDimitry Andric (isa<CXXThisExpr>(BaseExpr) && 10800b57cec5SDimitry Andric cast<CXXThisExpr>(BaseExpr)->isImplicit())) && 10810b57cec5SDimitry Andric !SuppressQualifierCheck && 10820b57cec5SDimitry Andric CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R)) 10830b57cec5SDimitry Andric return ExprError(); 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric // Construct an unresolved result if we in fact got an unresolved 10860b57cec5SDimitry Andric // result. 10870b57cec5SDimitry Andric if (R.isOverloadedResult() || R.isUnresolvableResult()) { 10880b57cec5SDimitry Andric // Suppress any lookup-related diagnostics; we'll do these when we 10890b57cec5SDimitry Andric // pick a member. 10900b57cec5SDimitry Andric R.suppressDiagnostics(); 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric UnresolvedMemberExpr *MemExpr 10930b57cec5SDimitry Andric = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(), 10940b57cec5SDimitry Andric BaseExpr, BaseExprType, 10950b57cec5SDimitry Andric IsArrow, OpLoc, 10960b57cec5SDimitry Andric SS.getWithLocInContext(Context), 10970b57cec5SDimitry Andric TemplateKWLoc, MemberNameInfo, 10980b57cec5SDimitry Andric TemplateArgs, R.begin(), R.end()); 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric return MemExpr; 11010b57cec5SDimitry Andric } 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andric assert(R.isSingleResult()); 11040b57cec5SDimitry Andric DeclAccessPair FoundDecl = R.begin().getPair(); 11050b57cec5SDimitry Andric NamedDecl *MemberDecl = R.getFoundDecl(); 11060b57cec5SDimitry Andric 11070b57cec5SDimitry Andric // FIXME: diagnose the presence of template arguments now. 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric // If the decl being referenced had an error, return an error for this 11100b57cec5SDimitry Andric // sub-expr without emitting another error, in order to avoid cascading 11110b57cec5SDimitry Andric // error cases. 11120b57cec5SDimitry Andric if (MemberDecl->isInvalidDecl()) 11130b57cec5SDimitry Andric return ExprError(); 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric // Handle the implicit-member-access case. 11160b57cec5SDimitry Andric if (!BaseExpr) { 11170b57cec5SDimitry Andric // If this is not an instance member, convert to a non-member access. 11180b57cec5SDimitry Andric if (!MemberDecl->isCXXInstanceMember()) { 1119e8d8bef9SDimitry Andric // We might have a variable template specialization (or maybe one day a 1120e8d8bef9SDimitry Andric // member concept-id). 1121e8d8bef9SDimitry Andric if (TemplateArgs || TemplateKWLoc.isValid()) 1122e8d8bef9SDimitry Andric return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/false, TemplateArgs); 1123e8d8bef9SDimitry Andric 11240b57cec5SDimitry Andric return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl, 11250b57cec5SDimitry Andric FoundDecl, TemplateArgs); 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric SourceLocation Loc = R.getNameLoc(); 11280b57cec5SDimitry Andric if (SS.getRange().isValid()) 11290b57cec5SDimitry Andric Loc = SS.getRange().getBegin(); 11300b57cec5SDimitry Andric BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true); 11310b57cec5SDimitry Andric } 11320b57cec5SDimitry Andric 11330b57cec5SDimitry Andric // Check the use of this member. 11340b57cec5SDimitry Andric if (DiagnoseUseOfDecl(MemberDecl, MemberLoc)) 11350b57cec5SDimitry Andric return ExprError(); 11360b57cec5SDimitry Andric 11370b57cec5SDimitry Andric if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) 11380b57cec5SDimitry Andric return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl, 11390b57cec5SDimitry Andric MemberNameInfo); 11400b57cec5SDimitry Andric 11410b57cec5SDimitry Andric if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl)) 11420b57cec5SDimitry Andric return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD, 11430b57cec5SDimitry Andric MemberNameInfo); 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) 11460b57cec5SDimitry Andric // We may have found a field within an anonymous union or struct 11470b57cec5SDimitry Andric // (C++ [class.union]). 11480b57cec5SDimitry Andric return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, 11490b57cec5SDimitry Andric FoundDecl, BaseExpr, 11500b57cec5SDimitry Andric OpLoc); 11510b57cec5SDimitry Andric 11520b57cec5SDimitry Andric if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { 11530fca6ea1SDimitry Andric return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, 11540fca6ea1SDimitry Andric SS.getWithLocInContext(Context), TemplateKWLoc, Var, 11550b57cec5SDimitry Andric FoundDecl, /*HadMultipleCandidates=*/false, 11560b57cec5SDimitry Andric MemberNameInfo, Var->getType().getNonReferenceType(), 11570b57cec5SDimitry Andric VK_LValue, OK_Ordinary); 11580b57cec5SDimitry Andric } 11590b57cec5SDimitry Andric 11600b57cec5SDimitry Andric if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) { 11610b57cec5SDimitry Andric ExprValueKind valueKind; 11620b57cec5SDimitry Andric QualType type; 11630b57cec5SDimitry Andric if (MemberFn->isInstance()) { 1164fe6060f1SDimitry Andric valueKind = VK_PRValue; 11650b57cec5SDimitry Andric type = Context.BoundMemberTy; 11660b57cec5SDimitry Andric } else { 11670b57cec5SDimitry Andric valueKind = VK_LValue; 11680b57cec5SDimitry Andric type = MemberFn->getType(); 11690b57cec5SDimitry Andric } 11700b57cec5SDimitry Andric 11710fca6ea1SDimitry Andric return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, 11720fca6ea1SDimitry Andric SS.getWithLocInContext(Context), TemplateKWLoc, 11730b57cec5SDimitry Andric MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, 11740b57cec5SDimitry Andric MemberNameInfo, type, valueKind, OK_Ordinary); 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { 11790fca6ea1SDimitry Andric return BuildMemberExpr( 11800fca6ea1SDimitry Andric BaseExpr, IsArrow, OpLoc, SS.getWithLocInContext(Context), 11810fca6ea1SDimitry Andric TemplateKWLoc, Enum, FoundDecl, /*HadMultipleCandidates=*/false, 11820fca6ea1SDimitry Andric MemberNameInfo, Enum->getType(), VK_PRValue, OK_Ordinary); 11830b57cec5SDimitry Andric } 1184e8d8bef9SDimitry Andric 11850b57cec5SDimitry Andric if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) { 1186e8d8bef9SDimitry Andric if (!TemplateArgs) { 11870fca6ea1SDimitry Andric diagnoseMissingTemplateArguments( 11880fca6ea1SDimitry Andric SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc); 1189e8d8bef9SDimitry Andric return ExprError(); 1190e8d8bef9SDimitry Andric } 1191e8d8bef9SDimitry Andric 1192e8d8bef9SDimitry Andric DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc, 1193e8d8bef9SDimitry Andric MemberNameInfo.getLoc(), *TemplateArgs); 1194e8d8bef9SDimitry Andric if (VDecl.isInvalid()) 1195e8d8bef9SDimitry Andric return ExprError(); 1196e8d8bef9SDimitry Andric 1197e8d8bef9SDimitry Andric // Non-dependent member, but dependent template arguments. 1198e8d8bef9SDimitry Andric if (!VDecl.get()) 1199e8d8bef9SDimitry Andric return ActOnDependentMemberExpr( 1200e8d8bef9SDimitry Andric BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc, 1201e8d8bef9SDimitry Andric FirstQualifierInScope, MemberNameInfo, TemplateArgs); 1202e8d8bef9SDimitry Andric 1203e8d8bef9SDimitry Andric VarDecl *Var = cast<VarDecl>(VDecl.get()); 1204e8d8bef9SDimitry Andric if (!Var->getTemplateSpecializationKind()) 1205e8d8bef9SDimitry Andric Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, MemberLoc); 1206e8d8bef9SDimitry Andric 12070fca6ea1SDimitry Andric return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, 12080fca6ea1SDimitry Andric SS.getWithLocInContext(Context), TemplateKWLoc, Var, 1209bdd1243dSDimitry Andric FoundDecl, /*HadMultipleCandidates=*/false, 1210bdd1243dSDimitry Andric MemberNameInfo, Var->getType().getNonReferenceType(), 1211bdd1243dSDimitry Andric VK_LValue, OK_Ordinary, TemplateArgs); 12120b57cec5SDimitry Andric } 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andric // We found something that we didn't expect. Complain. 12150b57cec5SDimitry Andric if (isa<TypeDecl>(MemberDecl)) 12160b57cec5SDimitry Andric Diag(MemberLoc, diag::err_typecheck_member_reference_type) 12170b57cec5SDimitry Andric << MemberName << BaseType << int(IsArrow); 12180b57cec5SDimitry Andric else 12190b57cec5SDimitry Andric Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) 12200b57cec5SDimitry Andric << MemberName << BaseType << int(IsArrow); 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric Diag(MemberDecl->getLocation(), diag::note_member_declared_here) 12230b57cec5SDimitry Andric << MemberName; 12240b57cec5SDimitry Andric R.suppressDiagnostics(); 12250b57cec5SDimitry Andric return ExprError(); 12260b57cec5SDimitry Andric } 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andric /// Given that normal member access failed on the given expression, 12290b57cec5SDimitry Andric /// and given that the expression's type involves builtin-id or 12300b57cec5SDimitry Andric /// builtin-Class, decide whether substituting in the redefinition 12310b57cec5SDimitry Andric /// types would be profitable. The redefinition type is whatever 12320b57cec5SDimitry Andric /// this translation unit tried to typedef to id/Class; we store 12330b57cec5SDimitry Andric /// it to the side and then re-use it in places like this. 12340b57cec5SDimitry Andric static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) { 12350b57cec5SDimitry Andric const ObjCObjectPointerType *opty 12360b57cec5SDimitry Andric = base.get()->getType()->getAs<ObjCObjectPointerType>(); 12370b57cec5SDimitry Andric if (!opty) return false; 12380b57cec5SDimitry Andric 12390b57cec5SDimitry Andric const ObjCObjectType *ty = opty->getObjectType(); 12400b57cec5SDimitry Andric 12410b57cec5SDimitry Andric QualType redef; 12420b57cec5SDimitry Andric if (ty->isObjCId()) { 12430b57cec5SDimitry Andric redef = S.Context.getObjCIdRedefinitionType(); 12440b57cec5SDimitry Andric } else if (ty->isObjCClass()) { 12450b57cec5SDimitry Andric redef = S.Context.getObjCClassRedefinitionType(); 12460b57cec5SDimitry Andric } else { 12470b57cec5SDimitry Andric return false; 12480b57cec5SDimitry Andric } 12490b57cec5SDimitry Andric 12500b57cec5SDimitry Andric // Do the substitution as long as the redefinition type isn't just a 12510b57cec5SDimitry Andric // possibly-qualified pointer to builtin-id or builtin-Class again. 12520b57cec5SDimitry Andric opty = redef->getAs<ObjCObjectPointerType>(); 12530b57cec5SDimitry Andric if (opty && !opty->getObjectType()->getInterface()) 12540b57cec5SDimitry Andric return false; 12550b57cec5SDimitry Andric 12560b57cec5SDimitry Andric base = S.ImpCastExprToType(base.get(), redef, CK_BitCast); 12570b57cec5SDimitry Andric return true; 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric 12600b57cec5SDimitry Andric static bool isRecordType(QualType T) { 12610b57cec5SDimitry Andric return T->isRecordType(); 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric static bool isPointerToRecordType(QualType T) { 12640b57cec5SDimitry Andric if (const PointerType *PT = T->getAs<PointerType>()) 12650b57cec5SDimitry Andric return PT->getPointeeType()->isRecordType(); 12660b57cec5SDimitry Andric return false; 12670b57cec5SDimitry Andric } 12680b57cec5SDimitry Andric 12690b57cec5SDimitry Andric ExprResult 12700b57cec5SDimitry Andric Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) { 12710b57cec5SDimitry Andric if (IsArrow && !Base->getType()->isFunctionType()) 12720b57cec5SDimitry Andric return DefaultFunctionArrayLvalueConversion(Base); 12730b57cec5SDimitry Andric 12740b57cec5SDimitry Andric return CheckPlaceholderExpr(Base); 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric /// Look up the given member of the given non-type-dependent 12780b57cec5SDimitry Andric /// expression. This can return in one of two ways: 12790b57cec5SDimitry Andric /// * If it returns a sentinel null-but-valid result, the caller will 12800b57cec5SDimitry Andric /// assume that lookup was performed and the results written into 12810b57cec5SDimitry Andric /// the provided structure. It will take over from there. 12820b57cec5SDimitry Andric /// * Otherwise, the returned expression will be produced in place of 12830b57cec5SDimitry Andric /// an ordinary member expression. 12840b57cec5SDimitry Andric /// 12850b57cec5SDimitry Andric /// The ObjCImpDecl bit is a gross hack that will need to be properly 12860b57cec5SDimitry Andric /// fixed for ObjC++. 12870b57cec5SDimitry Andric static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, 12880b57cec5SDimitry Andric ExprResult &BaseExpr, bool &IsArrow, 12890b57cec5SDimitry Andric SourceLocation OpLoc, CXXScopeSpec &SS, 12900b57cec5SDimitry Andric Decl *ObjCImpDecl, bool HasTemplateArgs, 12910b57cec5SDimitry Andric SourceLocation TemplateKWLoc) { 12920b57cec5SDimitry Andric assert(BaseExpr.get() && "no base expression"); 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric // Perform default conversions. 12950b57cec5SDimitry Andric BaseExpr = S.PerformMemberExprBaseConversion(BaseExpr.get(), IsArrow); 12960b57cec5SDimitry Andric if (BaseExpr.isInvalid()) 12970b57cec5SDimitry Andric return ExprError(); 12980b57cec5SDimitry Andric 12990b57cec5SDimitry Andric QualType BaseType = BaseExpr.get()->getType(); 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric DeclarationName MemberName = R.getLookupName(); 13020b57cec5SDimitry Andric SourceLocation MemberLoc = R.getNameLoc(); 13030b57cec5SDimitry Andric 13040b57cec5SDimitry Andric // For later type-checking purposes, turn arrow accesses into dot 13050b57cec5SDimitry Andric // accesses. The only access type we support that doesn't follow 13060b57cec5SDimitry Andric // the C equivalence "a->b === (*a).b" is ObjC property accesses, 13070b57cec5SDimitry Andric // and those never use arrows, so this is unaffected. 13080b57cec5SDimitry Andric if (IsArrow) { 13090b57cec5SDimitry Andric if (const PointerType *Ptr = BaseType->getAs<PointerType>()) 13100b57cec5SDimitry Andric BaseType = Ptr->getPointeeType(); 13110fca6ea1SDimitry Andric else if (const ObjCObjectPointerType *Ptr = 13120fca6ea1SDimitry Andric BaseType->getAs<ObjCObjectPointerType>()) 13130b57cec5SDimitry Andric BaseType = Ptr->getPointeeType(); 13140fca6ea1SDimitry Andric else if (BaseType->isFunctionType()) 13150fca6ea1SDimitry Andric goto fail; 13160fca6ea1SDimitry Andric else if (BaseType->isDependentType()) 13170fca6ea1SDimitry Andric BaseType = S.Context.DependentTy; 13180b57cec5SDimitry Andric else if (BaseType->isRecordType()) { 13190b57cec5SDimitry Andric // Recover from arrow accesses to records, e.g.: 13200b57cec5SDimitry Andric // struct MyRecord foo; 13210b57cec5SDimitry Andric // foo->bar 13220b57cec5SDimitry Andric // This is actually well-formed in C++ if MyRecord has an 13230b57cec5SDimitry Andric // overloaded operator->, but that should have been dealt with 13240b57cec5SDimitry Andric // by now--or a diagnostic message already issued if a problem 13250b57cec5SDimitry Andric // was encountered while looking for the overloaded operator->. 13260b57cec5SDimitry Andric if (!S.getLangOpts().CPlusPlus) { 13270b57cec5SDimitry Andric S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) 13280b57cec5SDimitry Andric << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() 13290b57cec5SDimitry Andric << FixItHint::CreateReplacement(OpLoc, "."); 13300b57cec5SDimitry Andric } 13310b57cec5SDimitry Andric IsArrow = false; 13320b57cec5SDimitry Andric } else { 13330b57cec5SDimitry Andric S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) 13340b57cec5SDimitry Andric << BaseType << BaseExpr.get()->getSourceRange(); 13350b57cec5SDimitry Andric return ExprError(); 13360b57cec5SDimitry Andric } 13370b57cec5SDimitry Andric } 13380b57cec5SDimitry Andric 133981ad6265SDimitry Andric // If the base type is an atomic type, this access is undefined behavior per 134081ad6265SDimitry Andric // C11 6.5.2.3p5. Instead of giving a typecheck error, we'll warn the user 134181ad6265SDimitry Andric // about the UB and recover by converting the atomic lvalue into a non-atomic 134281ad6265SDimitry Andric // lvalue. Because this is inherently unsafe as an atomic operation, the 134381ad6265SDimitry Andric // warning defaults to an error. 134481ad6265SDimitry Andric if (const auto *ATy = BaseType->getAs<AtomicType>()) { 134581ad6265SDimitry Andric S.DiagRuntimeBehavior(OpLoc, nullptr, 134681ad6265SDimitry Andric S.PDiag(diag::warn_atomic_member_access)); 134781ad6265SDimitry Andric BaseType = ATy->getValueType().getUnqualifiedType(); 134881ad6265SDimitry Andric BaseExpr = ImplicitCastExpr::Create( 134981ad6265SDimitry Andric S.Context, IsArrow ? S.Context.getPointerType(BaseType) : BaseType, 135081ad6265SDimitry Andric CK_AtomicToNonAtomic, BaseExpr.get(), nullptr, 135181ad6265SDimitry Andric BaseExpr.get()->getValueKind(), FPOptionsOverride()); 135281ad6265SDimitry Andric } 135381ad6265SDimitry Andric 13540b57cec5SDimitry Andric // Handle field access to simple records. 13550fca6ea1SDimitry Andric if (BaseType->getAsRecordDecl()) { 13560b57cec5SDimitry Andric TypoExpr *TE = nullptr; 13570fca6ea1SDimitry Andric if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow, 13580fca6ea1SDimitry Andric SS, HasTemplateArgs, TemplateKWLoc, TE)) 13590b57cec5SDimitry Andric return ExprError(); 13600b57cec5SDimitry Andric 13610b57cec5SDimitry Andric // Returning valid-but-null is how we indicate to the caller that 13620b57cec5SDimitry Andric // the lookup result was filled in. If typo correction was attempted and 13630b57cec5SDimitry Andric // failed, the lookup result will have been cleared--that combined with the 13640b57cec5SDimitry Andric // valid-but-null ExprResult will trigger the appropriate diagnostics. 13650b57cec5SDimitry Andric return ExprResult(TE); 13660fca6ea1SDimitry Andric } else if (BaseType->isDependentType()) { 13670fca6ea1SDimitry Andric R.setNotFoundInCurrentInstantiation(); 13680fca6ea1SDimitry Andric return ExprEmpty(); 13690b57cec5SDimitry Andric } 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric // Handle ivar access to Objective-C objects. 13720b57cec5SDimitry Andric if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) { 13730b57cec5SDimitry Andric if (!SS.isEmpty() && !SS.isInvalid()) { 13740b57cec5SDimitry Andric S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access) 13750b57cec5SDimitry Andric << 1 << SS.getScopeRep() 13760b57cec5SDimitry Andric << FixItHint::CreateRemoval(SS.getRange()); 13770b57cec5SDimitry Andric SS.clear(); 13780b57cec5SDimitry Andric } 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); 13810b57cec5SDimitry Andric 13820b57cec5SDimitry Andric // There are three cases for the base type: 13830b57cec5SDimitry Andric // - builtin id (qualified or unqualified) 13840b57cec5SDimitry Andric // - builtin Class (qualified or unqualified) 13850b57cec5SDimitry Andric // - an interface 13860b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = OTy->getInterface(); 13870b57cec5SDimitry Andric if (!IDecl) { 13880b57cec5SDimitry Andric if (S.getLangOpts().ObjCAutoRefCount && 13890b57cec5SDimitry Andric (OTy->isObjCId() || OTy->isObjCClass())) 13900b57cec5SDimitry Andric goto fail; 13910b57cec5SDimitry Andric // There's an implicit 'isa' ivar on all objects. 13920b57cec5SDimitry Andric // But we only actually find it this way on objects of type 'id', 13930b57cec5SDimitry Andric // apparently. 13940b57cec5SDimitry Andric if (OTy->isObjCId() && Member->isStr("isa")) 13950b57cec5SDimitry Andric return new (S.Context) ObjCIsaExpr(BaseExpr.get(), IsArrow, MemberLoc, 13960b57cec5SDimitry Andric OpLoc, S.Context.getObjCClassType()); 13970b57cec5SDimitry Andric if (ShouldTryAgainWithRedefinitionType(S, BaseExpr)) 13980b57cec5SDimitry Andric return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, 13990b57cec5SDimitry Andric ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); 14000b57cec5SDimitry Andric goto fail; 14010b57cec5SDimitry Andric } 14020b57cec5SDimitry Andric 14030b57cec5SDimitry Andric if (S.RequireCompleteType(OpLoc, BaseType, 14040b57cec5SDimitry Andric diag::err_typecheck_incomplete_tag, 14050b57cec5SDimitry Andric BaseExpr.get())) 14060b57cec5SDimitry Andric return ExprError(); 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDeclared = nullptr; 14090b57cec5SDimitry Andric ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); 14100b57cec5SDimitry Andric 14110b57cec5SDimitry Andric if (!IV) { 14120b57cec5SDimitry Andric // Attempt to correct for typos in ivar names. 14130b57cec5SDimitry Andric DeclFilterCCC<ObjCIvarDecl> Validator{}; 14140b57cec5SDimitry Andric Validator.IsObjCIvarLookup = IsArrow; 14150b57cec5SDimitry Andric if (TypoCorrection Corrected = S.CorrectTypo( 14160b57cec5SDimitry Andric R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr, 14170b57cec5SDimitry Andric Validator, Sema::CTK_ErrorRecovery, IDecl)) { 14180b57cec5SDimitry Andric IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>(); 14190b57cec5SDimitry Andric S.diagnoseTypo( 14200b57cec5SDimitry Andric Corrected, 14210b57cec5SDimitry Andric S.PDiag(diag::err_typecheck_member_reference_ivar_suggest) 14220b57cec5SDimitry Andric << IDecl->getDeclName() << MemberName); 14230b57cec5SDimitry Andric 14240b57cec5SDimitry Andric // Figure out the class that declares the ivar. 14250b57cec5SDimitry Andric assert(!ClassDeclared); 14260b57cec5SDimitry Andric 14270b57cec5SDimitry Andric Decl *D = cast<Decl>(IV->getDeclContext()); 14280b57cec5SDimitry Andric if (auto *Category = dyn_cast<ObjCCategoryDecl>(D)) 14290b57cec5SDimitry Andric D = Category->getClassInterface(); 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric if (auto *Implementation = dyn_cast<ObjCImplementationDecl>(D)) 14320b57cec5SDimitry Andric ClassDeclared = Implementation->getClassInterface(); 14330b57cec5SDimitry Andric else if (auto *Interface = dyn_cast<ObjCInterfaceDecl>(D)) 14340b57cec5SDimitry Andric ClassDeclared = Interface; 14350b57cec5SDimitry Andric 14360b57cec5SDimitry Andric assert(ClassDeclared && "cannot query interface"); 14370b57cec5SDimitry Andric } else { 14380b57cec5SDimitry Andric if (IsArrow && 14390b57cec5SDimitry Andric IDecl->FindPropertyDeclaration( 14400b57cec5SDimitry Andric Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { 14410b57cec5SDimitry Andric S.Diag(MemberLoc, diag::err_property_found_suggest) 14420b57cec5SDimitry Andric << Member << BaseExpr.get()->getType() 14430b57cec5SDimitry Andric << FixItHint::CreateReplacement(OpLoc, "."); 14440b57cec5SDimitry Andric return ExprError(); 14450b57cec5SDimitry Andric } 14460b57cec5SDimitry Andric 14470b57cec5SDimitry Andric S.Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) 14480b57cec5SDimitry Andric << IDecl->getDeclName() << MemberName 14490b57cec5SDimitry Andric << BaseExpr.get()->getSourceRange(); 14500b57cec5SDimitry Andric return ExprError(); 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric } 14530b57cec5SDimitry Andric 14540b57cec5SDimitry Andric assert(ClassDeclared); 14550b57cec5SDimitry Andric 14560b57cec5SDimitry Andric // If the decl being referenced had an error, return an error for this 14570b57cec5SDimitry Andric // sub-expr without emitting another error, in order to avoid cascading 14580b57cec5SDimitry Andric // error cases. 14590b57cec5SDimitry Andric if (IV->isInvalidDecl()) 14600b57cec5SDimitry Andric return ExprError(); 14610b57cec5SDimitry Andric 14620b57cec5SDimitry Andric // Check whether we can reference this field. 14630b57cec5SDimitry Andric if (S.DiagnoseUseOfDecl(IV, MemberLoc)) 14640b57cec5SDimitry Andric return ExprError(); 14650b57cec5SDimitry Andric if (IV->getAccessControl() != ObjCIvarDecl::Public && 14660b57cec5SDimitry Andric IV->getAccessControl() != ObjCIvarDecl::Package) { 14670b57cec5SDimitry Andric ObjCInterfaceDecl *ClassOfMethodDecl = nullptr; 14680b57cec5SDimitry Andric if (ObjCMethodDecl *MD = S.getCurMethodDecl()) 14690b57cec5SDimitry Andric ClassOfMethodDecl = MD->getClassInterface(); 14700b57cec5SDimitry Andric else if (ObjCImpDecl && S.getCurFunctionDecl()) { 14710b57cec5SDimitry Andric // Case of a c-function declared inside an objc implementation. 14720b57cec5SDimitry Andric // FIXME: For a c-style function nested inside an objc implementation 14730b57cec5SDimitry Andric // class, there is no implementation context available, so we pass 14740b57cec5SDimitry Andric // down the context as argument to this routine. Ideally, this context 14750b57cec5SDimitry Andric // need be passed down in the AST node and somehow calculated from the 14760b57cec5SDimitry Andric // AST for a function decl. 14770b57cec5SDimitry Andric if (ObjCImplementationDecl *IMPD = 14780b57cec5SDimitry Andric dyn_cast<ObjCImplementationDecl>(ObjCImpDecl)) 14790b57cec5SDimitry Andric ClassOfMethodDecl = IMPD->getClassInterface(); 14800b57cec5SDimitry Andric else if (ObjCCategoryImplDecl* CatImplClass = 14810b57cec5SDimitry Andric dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl)) 14820b57cec5SDimitry Andric ClassOfMethodDecl = CatImplClass->getClassInterface(); 14830b57cec5SDimitry Andric } 14840b57cec5SDimitry Andric if (!S.getLangOpts().DebuggerSupport) { 14850b57cec5SDimitry Andric if (IV->getAccessControl() == ObjCIvarDecl::Private) { 14860b57cec5SDimitry Andric if (!declaresSameEntity(ClassDeclared, IDecl) || 14870b57cec5SDimitry Andric !declaresSameEntity(ClassOfMethodDecl, ClassDeclared)) 14880b57cec5SDimitry Andric S.Diag(MemberLoc, diag::err_private_ivar_access) 14890b57cec5SDimitry Andric << IV->getDeclName(); 14900b57cec5SDimitry Andric } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) 14910b57cec5SDimitry Andric // @protected 14920b57cec5SDimitry Andric S.Diag(MemberLoc, diag::err_protected_ivar_access) 14930b57cec5SDimitry Andric << IV->getDeclName(); 14940b57cec5SDimitry Andric } 14950b57cec5SDimitry Andric } 14960b57cec5SDimitry Andric bool warn = true; 14970b57cec5SDimitry Andric if (S.getLangOpts().ObjCWeak) { 14980b57cec5SDimitry Andric Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts(); 14990b57cec5SDimitry Andric if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp)) 15000b57cec5SDimitry Andric if (UO->getOpcode() == UO_Deref) 15010b57cec5SDimitry Andric BaseExp = UO->getSubExpr()->IgnoreParenCasts(); 15020b57cec5SDimitry Andric 15030b57cec5SDimitry Andric if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp)) 15040b57cec5SDimitry Andric if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { 15050b57cec5SDimitry Andric S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access); 15060b57cec5SDimitry Andric warn = false; 15070b57cec5SDimitry Andric } 15080b57cec5SDimitry Andric } 15090b57cec5SDimitry Andric if (warn) { 15100b57cec5SDimitry Andric if (ObjCMethodDecl *MD = S.getCurMethodDecl()) { 15110b57cec5SDimitry Andric ObjCMethodFamily MF = MD->getMethodFamily(); 15120fca6ea1SDimitry Andric warn = (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize && 15130fca6ea1SDimitry Andric !S.ObjC().IvarBacksCurrentMethodAccessor(IDecl, MD, IV)); 15140b57cec5SDimitry Andric } 15150b57cec5SDimitry Andric if (warn) 15160b57cec5SDimitry Andric S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName(); 15170b57cec5SDimitry Andric } 15180b57cec5SDimitry Andric 15190b57cec5SDimitry Andric ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr( 15200b57cec5SDimitry Andric IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(), 15210b57cec5SDimitry Andric IsArrow); 15220b57cec5SDimitry Andric 15230b57cec5SDimitry Andric if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { 15240b57cec5SDimitry Andric if (!S.isUnevaluatedContext() && 15250b57cec5SDimitry Andric !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) 15260b57cec5SDimitry Andric S.getCurFunction()->recordUseOfWeak(Result); 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric return Result; 15300b57cec5SDimitry Andric } 15310b57cec5SDimitry Andric 15320b57cec5SDimitry Andric // Objective-C property access. 15330b57cec5SDimitry Andric const ObjCObjectPointerType *OPT; 15340b57cec5SDimitry Andric if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) { 15350b57cec5SDimitry Andric if (!SS.isEmpty() && !SS.isInvalid()) { 15360b57cec5SDimitry Andric S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access) 15370b57cec5SDimitry Andric << 0 << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange()); 15380b57cec5SDimitry Andric SS.clear(); 15390b57cec5SDimitry Andric } 15400b57cec5SDimitry Andric 15410b57cec5SDimitry Andric // This actually uses the base as an r-value. 15420b57cec5SDimitry Andric BaseExpr = S.DefaultLvalueConversion(BaseExpr.get()); 15430b57cec5SDimitry Andric if (BaseExpr.isInvalid()) 15440b57cec5SDimitry Andric return ExprError(); 15450b57cec5SDimitry Andric 15460b57cec5SDimitry Andric assert(S.Context.hasSameUnqualifiedType(BaseType, 15470b57cec5SDimitry Andric BaseExpr.get()->getType())); 15480b57cec5SDimitry Andric 15490b57cec5SDimitry Andric IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); 15500b57cec5SDimitry Andric 15510b57cec5SDimitry Andric const ObjCObjectType *OT = OPT->getObjectType(); 15520b57cec5SDimitry Andric 15530b57cec5SDimitry Andric // id, with and without qualifiers. 15540b57cec5SDimitry Andric if (OT->isObjCId()) { 15550b57cec5SDimitry Andric // Check protocols on qualified interfaces. 15560b57cec5SDimitry Andric Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member); 15570b57cec5SDimitry Andric if (Decl *PMDecl = 15580b57cec5SDimitry Andric FindGetterSetterNameDecl(OPT, Member, Sel, S.Context)) { 15590b57cec5SDimitry Andric if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) { 15600b57cec5SDimitry Andric // Check the use of this declaration 15610b57cec5SDimitry Andric if (S.DiagnoseUseOfDecl(PD, MemberLoc)) 15620b57cec5SDimitry Andric return ExprError(); 15630b57cec5SDimitry Andric 15640b57cec5SDimitry Andric return new (S.Context) 15650b57cec5SDimitry Andric ObjCPropertyRefExpr(PD, S.Context.PseudoObjectTy, VK_LValue, 15660b57cec5SDimitry Andric OK_ObjCProperty, MemberLoc, BaseExpr.get()); 15670b57cec5SDimitry Andric } 15680b57cec5SDimitry Andric 15690b57cec5SDimitry Andric if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) { 15700b57cec5SDimitry Andric Selector SetterSel = 15710b57cec5SDimitry Andric SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(), 15720b57cec5SDimitry Andric S.PP.getSelectorTable(), 15730b57cec5SDimitry Andric Member); 15740b57cec5SDimitry Andric ObjCMethodDecl *SMD = nullptr; 15750b57cec5SDimitry Andric if (Decl *SDecl = FindGetterSetterNameDecl(OPT, 15760b57cec5SDimitry Andric /*Property id*/ nullptr, 15770b57cec5SDimitry Andric SetterSel, S.Context)) 15780b57cec5SDimitry Andric SMD = dyn_cast<ObjCMethodDecl>(SDecl); 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric return new (S.Context) 15810b57cec5SDimitry Andric ObjCPropertyRefExpr(OMD, SMD, S.Context.PseudoObjectTy, VK_LValue, 15820b57cec5SDimitry Andric OK_ObjCProperty, MemberLoc, BaseExpr.get()); 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric } 15850b57cec5SDimitry Andric // Use of id.member can only be for a property reference. Do not 15860b57cec5SDimitry Andric // use the 'id' redefinition in this case. 15870b57cec5SDimitry Andric if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr)) 15880b57cec5SDimitry Andric return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, 15890b57cec5SDimitry Andric ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); 15900b57cec5SDimitry Andric 15910b57cec5SDimitry Andric return ExprError(S.Diag(MemberLoc, diag::err_property_not_found) 15920b57cec5SDimitry Andric << MemberName << BaseType); 15930b57cec5SDimitry Andric } 15940b57cec5SDimitry Andric 15950b57cec5SDimitry Andric // 'Class', unqualified only. 15960b57cec5SDimitry Andric if (OT->isObjCClass()) { 15970b57cec5SDimitry Andric // Only works in a method declaration (??!). 15980b57cec5SDimitry Andric ObjCMethodDecl *MD = S.getCurMethodDecl(); 15990b57cec5SDimitry Andric if (!MD) { 16000b57cec5SDimitry Andric if (ShouldTryAgainWithRedefinitionType(S, BaseExpr)) 16010b57cec5SDimitry Andric return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, 16020b57cec5SDimitry Andric ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); 16030b57cec5SDimitry Andric 16040b57cec5SDimitry Andric goto fail; 16050b57cec5SDimitry Andric } 16060b57cec5SDimitry Andric 16070b57cec5SDimitry Andric // Also must look for a getter name which uses property syntax. 16080b57cec5SDimitry Andric Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member); 16090b57cec5SDimitry Andric ObjCInterfaceDecl *IFace = MD->getClassInterface(); 16100b57cec5SDimitry Andric if (!IFace) 16110b57cec5SDimitry Andric goto fail; 16120b57cec5SDimitry Andric 16130b57cec5SDimitry Andric ObjCMethodDecl *Getter; 16140b57cec5SDimitry Andric if ((Getter = IFace->lookupClassMethod(Sel))) { 16150b57cec5SDimitry Andric // Check the use of this method. 16160b57cec5SDimitry Andric if (S.DiagnoseUseOfDecl(Getter, MemberLoc)) 16170b57cec5SDimitry Andric return ExprError(); 16180b57cec5SDimitry Andric } else 16190b57cec5SDimitry Andric Getter = IFace->lookupPrivateMethod(Sel, false); 16200b57cec5SDimitry Andric // If we found a getter then this may be a valid dot-reference, we 16210b57cec5SDimitry Andric // will look for the matching setter, in case it is needed. 16220b57cec5SDimitry Andric Selector SetterSel = 16230b57cec5SDimitry Andric SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(), 16240b57cec5SDimitry Andric S.PP.getSelectorTable(), 16250b57cec5SDimitry Andric Member); 16260b57cec5SDimitry Andric ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); 16270b57cec5SDimitry Andric if (!Setter) { 16280b57cec5SDimitry Andric // If this reference is in an @implementation, also check for 'private' 16290b57cec5SDimitry Andric // methods. 16300b57cec5SDimitry Andric Setter = IFace->lookupPrivateMethod(SetterSel, false); 16310b57cec5SDimitry Andric } 16320b57cec5SDimitry Andric 16330b57cec5SDimitry Andric if (Setter && S.DiagnoseUseOfDecl(Setter, MemberLoc)) 16340b57cec5SDimitry Andric return ExprError(); 16350b57cec5SDimitry Andric 16360b57cec5SDimitry Andric if (Getter || Setter) { 16370b57cec5SDimitry Andric return new (S.Context) ObjCPropertyRefExpr( 16380b57cec5SDimitry Andric Getter, Setter, S.Context.PseudoObjectTy, VK_LValue, 16390b57cec5SDimitry Andric OK_ObjCProperty, MemberLoc, BaseExpr.get()); 16400b57cec5SDimitry Andric } 16410b57cec5SDimitry Andric 16420b57cec5SDimitry Andric if (ShouldTryAgainWithRedefinitionType(S, BaseExpr)) 16430b57cec5SDimitry Andric return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, 16440b57cec5SDimitry Andric ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); 16450b57cec5SDimitry Andric 16460b57cec5SDimitry Andric return ExprError(S.Diag(MemberLoc, diag::err_property_not_found) 16470b57cec5SDimitry Andric << MemberName << BaseType); 16480b57cec5SDimitry Andric } 16490b57cec5SDimitry Andric 16500b57cec5SDimitry Andric // Normal property access. 16510fca6ea1SDimitry Andric return S.ObjC().HandleExprPropertyRefExpr( 16520fca6ea1SDimitry Andric OPT, BaseExpr.get(), OpLoc, MemberName, MemberLoc, SourceLocation(), 16530fca6ea1SDimitry Andric QualType(), false); 16540b57cec5SDimitry Andric } 16550b57cec5SDimitry Andric 165681ad6265SDimitry Andric if (BaseType->isExtVectorBoolType()) { 165781ad6265SDimitry Andric // We disallow element access for ext_vector_type bool. There is no way to 165881ad6265SDimitry Andric // materialize a reference to a vector element as a pointer (each element is 165981ad6265SDimitry Andric // one bit in the vector). 166081ad6265SDimitry Andric S.Diag(R.getNameLoc(), diag::err_ext_vector_component_name_illegal) 166181ad6265SDimitry Andric << MemberName 166281ad6265SDimitry Andric << (BaseExpr.get() ? BaseExpr.get()->getSourceRange() : SourceRange()); 166381ad6265SDimitry Andric return ExprError(); 166481ad6265SDimitry Andric } 166581ad6265SDimitry Andric 16660b57cec5SDimitry Andric // Handle 'field access' to vectors, such as 'V.xx'. 16670b57cec5SDimitry Andric if (BaseType->isExtVectorType()) { 16680b57cec5SDimitry Andric // FIXME: this expr should store IsArrow. 16690b57cec5SDimitry Andric IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); 1670bdd1243dSDimitry Andric ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind()); 16710b57cec5SDimitry Andric QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc, 16720b57cec5SDimitry Andric Member, MemberLoc); 16730b57cec5SDimitry Andric if (ret.isNull()) 16740b57cec5SDimitry Andric return ExprError(); 16750b57cec5SDimitry Andric Qualifiers BaseQ = 16760b57cec5SDimitry Andric S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers(); 16770b57cec5SDimitry Andric ret = S.Context.getQualifiedType(ret, BaseQ); 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric return new (S.Context) 16800b57cec5SDimitry Andric ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc); 16810b57cec5SDimitry Andric } 16820b57cec5SDimitry Andric 16830b57cec5SDimitry Andric // Adjust builtin-sel to the appropriate redefinition type if that's 16840b57cec5SDimitry Andric // not just a pointer to builtin-sel again. 16850b57cec5SDimitry Andric if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) && 16860b57cec5SDimitry Andric !S.Context.getObjCSelRedefinitionType()->isObjCSelType()) { 16870b57cec5SDimitry Andric BaseExpr = S.ImpCastExprToType( 16880b57cec5SDimitry Andric BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast); 16890b57cec5SDimitry Andric return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, 16900b57cec5SDimitry Andric ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); 16910b57cec5SDimitry Andric } 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric // Failure cases. 16940b57cec5SDimitry Andric fail: 16950b57cec5SDimitry Andric 16960b57cec5SDimitry Andric // Recover from dot accesses to pointers, e.g.: 16970b57cec5SDimitry Andric // type *foo; 16980b57cec5SDimitry Andric // foo.bar 16990b57cec5SDimitry Andric // This is actually well-formed in two cases: 17000b57cec5SDimitry Andric // - 'type' is an Objective C type 17010b57cec5SDimitry Andric // - 'bar' is a pseudo-destructor name which happens to refer to 17020b57cec5SDimitry Andric // the appropriate pointer type 17030b57cec5SDimitry Andric if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { 17040b57cec5SDimitry Andric if (!IsArrow && Ptr->getPointeeType()->isRecordType() && 17050b57cec5SDimitry Andric MemberName.getNameKind() != DeclarationName::CXXDestructorName) { 17060b57cec5SDimitry Andric S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) 17070b57cec5SDimitry Andric << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() 17080b57cec5SDimitry Andric << FixItHint::CreateReplacement(OpLoc, "->"); 17090b57cec5SDimitry Andric 171004eeddc0SDimitry Andric if (S.isSFINAEContext()) 171104eeddc0SDimitry Andric return ExprError(); 171204eeddc0SDimitry Andric 17130b57cec5SDimitry Andric // Recurse as an -> access. 17140b57cec5SDimitry Andric IsArrow = true; 17150b57cec5SDimitry Andric return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, 17160b57cec5SDimitry Andric ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); 17170b57cec5SDimitry Andric } 17180b57cec5SDimitry Andric } 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric // If the user is trying to apply -> or . to a function name, it's probably 17210b57cec5SDimitry Andric // because they forgot parentheses to call that function. 17220b57cec5SDimitry Andric if (S.tryToRecoverWithCall( 17230b57cec5SDimitry Andric BaseExpr, S.PDiag(diag::err_member_reference_needs_call), 17240b57cec5SDimitry Andric /*complain*/ false, 17250b57cec5SDimitry Andric IsArrow ? &isPointerToRecordType : &isRecordType)) { 17260b57cec5SDimitry Andric if (BaseExpr.isInvalid()) 17270b57cec5SDimitry Andric return ExprError(); 17280b57cec5SDimitry Andric BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get()); 17290b57cec5SDimitry Andric return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, 17300b57cec5SDimitry Andric ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); 17310b57cec5SDimitry Andric } 17320b57cec5SDimitry Andric 17335f757f3fSDimitry Andric // HLSL supports implicit conversion of scalar types to single element vector 17345f757f3fSDimitry Andric // rvalues in member expressions. 17355f757f3fSDimitry Andric if (S.getLangOpts().HLSL && BaseType->isScalarType()) { 17365f757f3fSDimitry Andric QualType VectorTy = S.Context.getExtVectorType(BaseType, 1); 17375f757f3fSDimitry Andric BaseExpr = S.ImpCastExprToType(BaseExpr.get(), VectorTy, CK_VectorSplat, 17385f757f3fSDimitry Andric BaseExpr.get()->getValueKind()); 17395f757f3fSDimitry Andric return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl, 17405f757f3fSDimitry Andric HasTemplateArgs, TemplateKWLoc); 17415f757f3fSDimitry Andric } 17425f757f3fSDimitry Andric 17430b57cec5SDimitry Andric S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union) 17440b57cec5SDimitry Andric << BaseType << BaseExpr.get()->getSourceRange() << MemberLoc; 17450b57cec5SDimitry Andric 17460b57cec5SDimitry Andric return ExprError(); 17470b57cec5SDimitry Andric } 17480b57cec5SDimitry Andric 17490b57cec5SDimitry Andric ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, 17500b57cec5SDimitry Andric SourceLocation OpLoc, 17510fca6ea1SDimitry Andric tok::TokenKind OpKind, CXXScopeSpec &SS, 17520b57cec5SDimitry Andric SourceLocation TemplateKWLoc, 17530fca6ea1SDimitry Andric UnqualifiedId &Id, Decl *ObjCImpDecl) { 17540b57cec5SDimitry Andric // Warn about the explicit constructor calls Microsoft extension. 17550b57cec5SDimitry Andric if (getLangOpts().MicrosoftExt && 17560b57cec5SDimitry Andric Id.getKind() == UnqualifiedIdKind::IK_ConstructorName) 17570b57cec5SDimitry Andric Diag(Id.getSourceRange().getBegin(), 17580b57cec5SDimitry Andric diag::ext_ms_explicit_constructor_call); 17590b57cec5SDimitry Andric 17600b57cec5SDimitry Andric TemplateArgumentListInfo TemplateArgsBuffer; 17610b57cec5SDimitry Andric 17620b57cec5SDimitry Andric // Decompose the name into its component parts. 17630b57cec5SDimitry Andric DeclarationNameInfo NameInfo; 17640b57cec5SDimitry Andric const TemplateArgumentListInfo *TemplateArgs; 17650b57cec5SDimitry Andric DecomposeUnqualifiedId(Id, TemplateArgsBuffer, 17660b57cec5SDimitry Andric NameInfo, TemplateArgs); 17670b57cec5SDimitry Andric 17680b57cec5SDimitry Andric bool IsArrow = (OpKind == tok::arrow); 17690b57cec5SDimitry Andric 177081ad6265SDimitry Andric if (getLangOpts().HLSL && IsArrow) 177181ad6265SDimitry Andric return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2); 177281ad6265SDimitry Andric 17730b57cec5SDimitry Andric NamedDecl *FirstQualifierInScope 17740b57cec5SDimitry Andric = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep())); 17750b57cec5SDimitry Andric 17760b57cec5SDimitry Andric // This is a postfix expression, so get rid of ParenListExprs. 17770b57cec5SDimitry Andric ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); 17780b57cec5SDimitry Andric if (Result.isInvalid()) return ExprError(); 17790b57cec5SDimitry Andric Base = Result.get(); 17800b57cec5SDimitry Andric 17810b57cec5SDimitry Andric ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; 17820b57cec5SDimitry Andric ExprResult Res = BuildMemberReferenceExpr( 17830b57cec5SDimitry Andric Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, 17840b57cec5SDimitry Andric FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs); 17850b57cec5SDimitry Andric 17860b57cec5SDimitry Andric if (!Res.isInvalid() && isa<MemberExpr>(Res.get())) 17870b57cec5SDimitry Andric CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get())); 17880b57cec5SDimitry Andric 17890b57cec5SDimitry Andric return Res; 17900b57cec5SDimitry Andric } 17910b57cec5SDimitry Andric 17920b57cec5SDimitry Andric void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) { 1793e8d8bef9SDimitry Andric if (isUnevaluatedContext()) 17940b57cec5SDimitry Andric return; 17950b57cec5SDimitry Andric 1796e8d8bef9SDimitry Andric QualType ResultTy = E->getType(); 1797e8d8bef9SDimitry Andric 1798e8d8bef9SDimitry Andric // Member accesses have four cases: 1799e8d8bef9SDimitry Andric // 1: non-array member via "->": dereferences 1800e8d8bef9SDimitry Andric // 2: non-array member via ".": nothing interesting happens 1801e8d8bef9SDimitry Andric // 3: array member access via "->": nothing interesting happens 1802e8d8bef9SDimitry Andric // (this returns an array lvalue and does not actually dereference memory) 1803e8d8bef9SDimitry Andric // 4: array member access via ".": *adds* a layer of indirection 1804e8d8bef9SDimitry Andric if (ResultTy->isArrayType()) { 1805e8d8bef9SDimitry Andric if (!E->isArrow()) { 1806e8d8bef9SDimitry Andric // This might be something like: 1807e8d8bef9SDimitry Andric // (*structPtr).arrayMember 1808e8d8bef9SDimitry Andric // which behaves roughly like: 1809e8d8bef9SDimitry Andric // &(*structPtr).pointerMember 1810e8d8bef9SDimitry Andric // in that the apparent dereference in the base expression does not 1811e8d8bef9SDimitry Andric // actually happen. 1812e8d8bef9SDimitry Andric CheckAddressOfNoDeref(E->getBase()); 1813e8d8bef9SDimitry Andric } 1814e8d8bef9SDimitry Andric } else if (E->isArrow()) { 18150b57cec5SDimitry Andric if (const auto *Ptr = dyn_cast<PointerType>( 18160b57cec5SDimitry Andric E->getBase()->getType().getDesugaredType(Context))) { 18170b57cec5SDimitry Andric if (Ptr->getPointeeType()->hasAttr(attr::NoDeref)) 18180b57cec5SDimitry Andric ExprEvalContexts.back().PossibleDerefs.insert(E); 18190b57cec5SDimitry Andric } 18200b57cec5SDimitry Andric } 18210b57cec5SDimitry Andric } 18220b57cec5SDimitry Andric 18230b57cec5SDimitry Andric ExprResult 18240b57cec5SDimitry Andric Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, 18250b57cec5SDimitry Andric SourceLocation OpLoc, const CXXScopeSpec &SS, 18260b57cec5SDimitry Andric FieldDecl *Field, DeclAccessPair FoundDecl, 18270b57cec5SDimitry Andric const DeclarationNameInfo &MemberNameInfo) { 18280b57cec5SDimitry Andric // x.a is an l-value if 'a' has a reference type. Otherwise: 18290b57cec5SDimitry Andric // x.a is an l-value/x-value/pr-value if the base is (and note 18300b57cec5SDimitry Andric // that *x is always an l-value), except that if the base isn't 18310b57cec5SDimitry Andric // an ordinary object then we must have an rvalue. 18320b57cec5SDimitry Andric ExprValueKind VK = VK_LValue; 18330b57cec5SDimitry Andric ExprObjectKind OK = OK_Ordinary; 18340b57cec5SDimitry Andric if (!IsArrow) { 18350b57cec5SDimitry Andric if (BaseExpr->getObjectKind() == OK_Ordinary) 18360b57cec5SDimitry Andric VK = BaseExpr->getValueKind(); 18370b57cec5SDimitry Andric else 1838fe6060f1SDimitry Andric VK = VK_PRValue; 18390b57cec5SDimitry Andric } 1840fe6060f1SDimitry Andric if (VK != VK_PRValue && Field->isBitField()) 18410b57cec5SDimitry Andric OK = OK_BitField; 18420b57cec5SDimitry Andric 18430b57cec5SDimitry Andric // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] 18440b57cec5SDimitry Andric QualType MemberType = Field->getType(); 18450b57cec5SDimitry Andric if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) { 18460b57cec5SDimitry Andric MemberType = Ref->getPointeeType(); 18470b57cec5SDimitry Andric VK = VK_LValue; 18480b57cec5SDimitry Andric } else { 18490b57cec5SDimitry Andric QualType BaseType = BaseExpr->getType(); 1850fe6060f1SDimitry Andric if (IsArrow) BaseType = BaseType->castAs<PointerType>()->getPointeeType(); 18510b57cec5SDimitry Andric 18520b57cec5SDimitry Andric Qualifiers BaseQuals = BaseType.getQualifiers(); 18530b57cec5SDimitry Andric 18540b57cec5SDimitry Andric // GC attributes are never picked up by members. 18550b57cec5SDimitry Andric BaseQuals.removeObjCGCAttr(); 18560b57cec5SDimitry Andric 18570b57cec5SDimitry Andric // CVR attributes from the base are picked up by members, 18580b57cec5SDimitry Andric // except that 'mutable' members don't pick up 'const'. 18590b57cec5SDimitry Andric if (Field->isMutable()) BaseQuals.removeConst(); 18600b57cec5SDimitry Andric 18610b57cec5SDimitry Andric Qualifiers MemberQuals = 18620b57cec5SDimitry Andric Context.getCanonicalType(MemberType).getQualifiers(); 18630b57cec5SDimitry Andric 18640b57cec5SDimitry Andric assert(!MemberQuals.hasAddressSpace()); 18650b57cec5SDimitry Andric 18660b57cec5SDimitry Andric Qualifiers Combined = BaseQuals + MemberQuals; 18670b57cec5SDimitry Andric if (Combined != MemberQuals) 18680b57cec5SDimitry Andric MemberType = Context.getQualifiedType(MemberType, Combined); 1869e8d8bef9SDimitry Andric 1870e8d8bef9SDimitry Andric // Pick up NoDeref from the base in case we end up using AddrOf on the 1871e8d8bef9SDimitry Andric // result. E.g. the expression 1872e8d8bef9SDimitry Andric // &someNoDerefPtr->pointerMember 1873e8d8bef9SDimitry Andric // should be a noderef pointer again. 1874e8d8bef9SDimitry Andric if (BaseType->hasAttr(attr::NoDeref)) 1875e8d8bef9SDimitry Andric MemberType = 1876e8d8bef9SDimitry Andric Context.getAttributedType(attr::NoDeref, MemberType, MemberType); 18770b57cec5SDimitry Andric } 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext); 18800b57cec5SDimitry Andric if (!(CurMethod && CurMethod->isDefaulted())) 18810b57cec5SDimitry Andric UnusedPrivateFields.remove(Field); 18820b57cec5SDimitry Andric 18830b57cec5SDimitry Andric ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), 18840b57cec5SDimitry Andric FoundDecl, Field); 18850b57cec5SDimitry Andric if (Base.isInvalid()) 18860b57cec5SDimitry Andric return ExprError(); 18870b57cec5SDimitry Andric 18880b57cec5SDimitry Andric // Build a reference to a private copy for non-static data members in 18890b57cec5SDimitry Andric // non-static member functions, privatized by OpenMP constructs. 18900b57cec5SDimitry Andric if (getLangOpts().OpenMP && IsArrow && 18910b57cec5SDimitry Andric !CurContext->isDependentContext() && 18920b57cec5SDimitry Andric isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) { 18930fca6ea1SDimitry Andric if (auto *PrivateCopy = OpenMP().isOpenMPCapturedDecl(Field)) { 18940fca6ea1SDimitry Andric return OpenMP().getOpenMPCapturedExpr(PrivateCopy, VK, OK, 18950b57cec5SDimitry Andric MemberNameInfo.getLoc()); 18960b57cec5SDimitry Andric } 18970b57cec5SDimitry Andric } 18980b57cec5SDimitry Andric 18990fca6ea1SDimitry Andric return BuildMemberExpr( 19000fca6ea1SDimitry Andric Base.get(), IsArrow, OpLoc, SS.getWithLocInContext(Context), 19010b57cec5SDimitry Andric /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, 19020fca6ea1SDimitry Andric /*HadMultipleCandidates=*/false, MemberNameInfo, MemberType, VK, OK); 19030b57cec5SDimitry Andric } 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric ExprResult 19060b57cec5SDimitry Andric Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, 19070b57cec5SDimitry Andric SourceLocation TemplateKWLoc, 19080b57cec5SDimitry Andric LookupResult &R, 19090b57cec5SDimitry Andric const TemplateArgumentListInfo *TemplateArgs, 19100b57cec5SDimitry Andric bool IsKnownInstance, const Scope *S) { 19110b57cec5SDimitry Andric assert(!R.empty() && !R.isAmbiguous()); 19120b57cec5SDimitry Andric 19130b57cec5SDimitry Andric SourceLocation loc = R.getNameLoc(); 19140b57cec5SDimitry Andric 19150b57cec5SDimitry Andric // If this is known to be an instance access, go ahead and build an 19160b57cec5SDimitry Andric // implicit 'this' expression now. 19170b57cec5SDimitry Andric QualType ThisTy = getCurrentThisType(); 19180b57cec5SDimitry Andric assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'"); 19190b57cec5SDimitry Andric 19200b57cec5SDimitry Andric Expr *baseExpr = nullptr; // null signifies implicit access 19210b57cec5SDimitry Andric if (IsKnownInstance) { 19220b57cec5SDimitry Andric SourceLocation Loc = R.getNameLoc(); 19230b57cec5SDimitry Andric if (SS.getRange().isValid()) 19240b57cec5SDimitry Andric Loc = SS.getRange().getBegin(); 19250b57cec5SDimitry Andric baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true); 19260b57cec5SDimitry Andric } 19270b57cec5SDimitry Andric 19285f757f3fSDimitry Andric return BuildMemberReferenceExpr( 19295f757f3fSDimitry Andric baseExpr, ThisTy, 19305f757f3fSDimitry Andric /*OpLoc=*/SourceLocation(), 19315f757f3fSDimitry Andric /*IsArrow=*/!getLangOpts().HLSL, SS, TemplateKWLoc, 19325f757f3fSDimitry Andric /*FirstQualifierInScope=*/nullptr, R, TemplateArgs, S); 19330b57cec5SDimitry Andric } 1934