diff options
author | John McCall <rjmccall@apple.com> | 2009-11-24 19:00:30 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-11-24 19:00:30 +0000 |
commit | f7a1a744eba4b29ceb0f20af8f34515d892fdd64 (patch) | |
tree | 9698ed40b4b0973e9f2e64c7af2fd896b154ed43 /lib/Sema | |
parent | 909e58988b3a3bb2ad36bec03aafa1302544fd73 (diff) |
Rip out TemplateIdRefExpr and make UnresolvedLookupExpr and
DependentScopeDeclRefExpr support storing templateids. Unite the common
code paths between ActOnDeclarationNameExpr and ActOnTemplateIdExpr.
This gets us to a point where we don't need to store function templates in
the AST using TemplateNames, which is critical to ripping out OverloadedFunction.
Also resolves a few FIXMEs.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89785 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Lookup.h | 13 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 68 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 506 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 91 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 366 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 48 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 196 |
11 files changed, 727 insertions, 582 deletions
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index b30590661c..c7b574fd66 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -379,14 +379,14 @@ public: class Filter { LookupResult &Results; unsigned I; - bool ErasedAny; + bool Changed; #ifndef NDEBUG bool CalledDone; #endif friend class LookupResult; Filter(LookupResult &Results) - : Results(Results), I(0), ErasedAny(false) + : Results(Results), I(0), Changed(false) #ifndef NDEBUG , CalledDone(false) #endif @@ -413,7 +413,12 @@ public: void erase() { Results.Decls[--I] = Results.Decls.back(); Results.Decls.pop_back(); - ErasedAny = true; + Changed = true; + } + + void replace(NamedDecl *D) { + Results.Decls[I-1] = D; + Changed = true; } void done() { @@ -422,7 +427,7 @@ public: CalledDone = true; #endif - if (ErasedAny) + if (Changed) Results.resolveKindAfterFilter(); } }; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3b3b41ba21..beaccdac2f 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1389,6 +1389,16 @@ public: UnqualifiedId &Name, bool HasTrailingLParen, bool IsAddressOfOperand); + + OwningExprResult LookupInObjCMethod(LookupResult &R, + Scope *S, + IdentifierInfo *II); + + OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + bool CheckForImplicitMember, + const TemplateArgumentListInfo *TemplateArgs); OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, @@ -1400,26 +1410,25 @@ public: FieldDecl *Field, Expr *BaseObjectExpr = 0, SourceLocation OpLoc = SourceLocation()); - OwningExprResult ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, - DeclarationName Name, - bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand = false); - OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS, - LookupResult &R); - bool UseArgumentDependentLookup(const CXXScopeSpec *SS, + OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs); + bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, bool HasTrailingLParen); - OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS, - LookupResult &R, bool ADL); - OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS, - SourceLocation Loc, - DeclarationName Name, - bool NeedsADL, - bool IsOverloaded, - NamedDecl * const *Decls, - unsigned NumDecls); - OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS, + + OwningExprResult BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc); + OwningExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs); + + OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool ADL); + OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, SourceLocation Loc, NamedDecl *D); @@ -2110,7 +2119,7 @@ public: FunctionDecl::StorageClass& SC); DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion); - bool isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, + bool isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D, SourceLocation NameLoc, QualType &ThisType, QualType &MemberType); @@ -2207,6 +2216,9 @@ public: //===--------------------------------------------------------------------===// // C++ Templates [C++ 14] // + void LookupTemplateName(LookupResult &R, Scope *S, const CXXScopeSpec &SS, + QualType ObjectType, bool EnteringContext); + virtual TemplateNameKind isTemplateName(Scope *S, const CXXScopeSpec &SS, UnqualifiedId &Name, @@ -2286,18 +2298,14 @@ public: DeclSpec::TST TagSpec, SourceLocation TagLoc); - OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, + OwningExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs); + OwningExprResult BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, const TemplateArgumentListInfo &TemplateArgs); - - OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc); virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, const CXXScopeSpec &SS, diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index a555a64ddf..b4947242bd 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1967,8 +1967,10 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, if (!CDecl && FName->isStr("super")) { // "super" may be the name of a variable, in which case we are // probably calling an instance method. - OwningExprResult Super = ActOnDeclarationNameExpr(S, FNameLoc, FName, - false, 0, false); + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(FName, FNameLoc); + OwningExprResult Super = ActOnIdExpression(S, SS, id, false, false); return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(), SelIdents, NumSelIdents); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 3fa7d9cdde..2405d52890 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -177,9 +177,10 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, // Special case where the argument is a template id. if (Attr.getParameterName()) { - sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(), - Attr.getParameterName(), - false, 0, false).takeAs<Expr>(); + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); + sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>(); } else { // check the attribute arguments. if (Attr.getNumArgs() != 1) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 9d7a42172c..50fd5ec9b1 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -617,202 +617,140 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, return Owned(Result); } +static void DecomposeTemplateName(LookupResult &R, TemplateName TName) { + if (TemplateDecl *TD = TName.getAsTemplateDecl()) + R.addDecl(TD); + else if (OverloadedFunctionDecl *OD + = TName.getAsOverloadedFunctionDecl()) + for (OverloadIterator I(OD), E; I != E; ++I) + R.addDecl(*I); + + R.resolveKind(); +} + Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, const CXXScopeSpec &SS, - UnqualifiedId &Name, + UnqualifiedId &Id, bool HasTrailingLParen, - bool IsAddressOfOperand) { - assert(!(IsAddressOfOperand && HasTrailingLParen) && + bool isAddressOfOperand) { + assert(!(isAddressOfOperand && HasTrailingLParen) && "cannot be direct & operand and have a trailing lparen"); - if (Name.getKind() == UnqualifiedId::IK_TemplateId) { + if (SS.isInvalid()) + return ExprError(); + + TemplateArgumentListInfo ExplicitTemplateArgs; + + // Decompose the UnqualifiedId into the following data. + DeclarationName Name; + SourceLocation NameLoc; + const TemplateArgumentListInfo *TemplateArgs; + if (Id.getKind() == UnqualifiedId::IK_TemplateId) { + ExplicitTemplateArgs.setLAngleLoc(Id.TemplateId->LAngleLoc); + ExplicitTemplateArgs.setRAngleLoc(Id.TemplateId->RAngleLoc); + ASTTemplateArgsPtr TemplateArgsPtr(*this, - Name.TemplateId->getTemplateArgs(), - Name.TemplateId->NumArgs); - return ActOnTemplateIdExpr(SS, - TemplateTy::make(Name.TemplateId->Template), - Name.TemplateId->TemplateNameLoc, - Name.TemplateId->LAngleLoc, - TemplateArgsPtr, - Name.TemplateId->RAngleLoc); - } - - // FIXME: We lose a bunch of source information by doing this. Later, - // we'll want to merge ActOnDeclarationNameExpr's logic into - // ActOnIdExpression. - return ActOnDeclarationNameExpr(S, - Name.StartLocation, - GetNameFromUnqualifiedId(Name), - HasTrailingLParen, - &SS, - IsAddressOfOperand); -} + Id.TemplateId->getTemplateArgs(), + Id.TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, ExplicitTemplateArgs); + TemplateArgsPtr.release(); -/// ActOnDeclarationNameExpr - The parser has read some kind of name -/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine -/// performs lookup on that name and returns an expression that refers -/// to that name. This routine isn't directly called from the parser, -/// because the parser doesn't know about DeclarationName. Rather, -/// this routine is called by ActOnIdExpression, which contains a -/// parsed UnqualifiedId. -/// -/// HasTrailingLParen indicates whether this identifier is used in a -/// function call context. LookupCtx is only used for a C++ -/// qualified-id (foo::bar) to indicate the class or namespace that -/// the identifier must be a member of. -/// -/// isAddressOfOperand means that this expression is the direct operand -/// of an address-of operator. This matters because this is the only -/// situation where a qualified name referencing a non-static member may -/// appear outside a member function of this class. -Sema::OwningExprResult -Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, - DeclarationName Name, bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand) { - // Could be enum-constant, value decl, instance variable, etc. - if (SS && SS->isInvalid()) - return ExprError(); + TemplateName TName = + TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>(); - // Determine whether this is a member of an unknown specialization. - if (SS && SS->isSet() && !computeDeclContext(*SS, false)) { - return Owned(new (Context) DependentScopeDeclRefExpr(Name, Context.DependentTy, - Loc, SS->getRange(), - static_cast<NestedNameSpecifier *>(SS->getScopeRep()), - isAddressOfOperand)); + Name = Context.getNameForTemplate(TName); + NameLoc = Id.TemplateId->TemplateNameLoc; + TemplateArgs = &ExplicitTemplateArgs; + } else { + Name = GetNameFromUnqualifiedId(Id); + NameLoc = Id.StartLocation; + TemplateArgs = 0; } - LookupResult Lookup(*this, Name, Loc, LookupOrdinaryName); - LookupParsedName(Lookup, S, SS, true); + IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (Lookup.isAmbiguous()) - return ExprError(); + // C++ [temp.dep.expr]p3: + // An id-expression is type-dependent if it contains: + // -- a nested-name-specifier that contains a class-name that + // names a dependent type. + // Determine whether this is a member of an unknown specialization; + // we need to handle these differently. + if (SS.isSet() && !computeDeclContext(SS, false)) { + bool CheckForImplicitMember = !isAddressOfOperand; - // If this reference is in an Objective-C method, then ivar lookup happens as - // well. - IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (II && getCurMethodDecl()) { - // There are two cases to handle here. 1) scoped lookup could have failed, - // in which case we should look for an ivar. 2) scoped lookup could have - // found a decl, but that decl is outside the current instance method (i.e. - // a global variable). In these two cases, we do a lookup for an ivar with - // this name, if the lookup sucedes, we replace it our current decl. - - // FIXME: we should change lookup to do this. - - // If we're in a class method, we don't normally want to look for - // ivars. But if we don't find anything else, and there's an - // ivar, that's an error. - bool IsClassMethod = getCurMethodDecl()->isClassMethod(); - - bool LookForIvars; - if (Lookup.empty()) - LookForIvars = true; - else if (IsClassMethod) - LookForIvars = false; - else - LookForIvars = (Lookup.isSingleResult() && - Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + return ActOnDependentIdExpression(SS, Name, NameLoc, + CheckForImplicitMember, + TemplateArgs); + } - if (LookForIvars) { - ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - // Diagnose using an ivar in a class method. - if (IsClassMethod) - return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) - << IV->getDeclName()); - - // If we're referencing an invalid decl, just return this as a silent - // error node. The error diagnostic was already emitted on the decl. - if (IV->isInvalidDecl()) - return ExprError(); + // Perform the required lookup. + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + if (TemplateArgs) { + TemplateName TName = + TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>(); - // Check if referencing a field with __attribute__((deprecated)). - if (DiagnoseUseOfDecl(IV, Loc)) - return ExprError(); + // Just re-use the lookup done by isTemplateName. + DecomposeTemplateName(R, TName); + } else { + LookupParsedName(R, S, &SS, true); - // Diagnose the use of an ivar outside of the declaring class. - if (IV->getAccessControl() == ObjCIvarDecl::Private && - ClassDeclared != IFace) - Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); - - // FIXME: This should use a new expr for a direct reference, don't - // turn this into Self->ivar, just return a BareIVarExpr or something. - IdentifierInfo &II = Context.Idents.get("self"); - UnqualifiedId SelfName; - SelfName.setIdentifier(&II, SourceLocation()); - CXXScopeSpec SelfScopeSpec; - OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, - SelfName, false, false); - MarkDeclarationReferenced(Loc, IV); - return Owned(new (Context) - ObjCIvarRefExpr(IV, IV->getType(), Loc, - SelfExpr.takeAs<Expr>(), true, true)); - } - } else if (getCurMethodDecl()->isInstanceMethod()) { - // We should warn if a local variable hides an ivar. - ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); - ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { - if (IV->getAccessControl() != ObjCIvarDecl::Private || - IFace == ClassDeclared) - Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); - } - } - // Needed to implement property "super.method" notation. - if (Lookup.empty() && II->isStr("super")) { - QualType T; + // If this reference is in an Objective-C method, then we need to do + // some special Objective-C lookup, too. + if (!SS.isSet() && II && getCurMethodDecl()) { + OwningExprResult E(LookupInObjCMethod(R, S, II)); + if (E.isInvalid()) + return ExprError(); - if (getCurMethodDecl()->isInstanceMethod()) - T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType( - getCurMethodDecl()->getClassInterface())); - else - T = Context.getObjCClassType(); - return Owned(new (Context) ObjCSuperExpr(Loc, T)); + Expr *Ex = E.takeAs<Expr>(); + if (Ex) return Owned(Ex); } } + if (R.isAmbiguous()) + return ExprError(); + // Determine whether this name might be a candidate for // argument-dependent lookup. - bool ADL = UseArgumentDependentLookup(SS, Lookup, HasTrailingLParen); + bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen); - if (Lookup.empty() && !ADL) { + if (R.empty() && !ADL) { // Otherwise, this could be an implicitly declared function reference (legal - // in C90, extension in C99). - if (HasTrailingLParen && II && - !getLangOptions().CPlusPlus) { // Not in C++. - NamedDecl *D = ImplicitlyDefineFunction(Loc, *II, S); - if (D) Lookup.addDecl(D); - } else { - // If this name wasn't predeclared and if this is not a function call, - // diagnose the problem. - if (SS && !SS->isEmpty()) - return ExprError(Diag(Loc, diag::err_no_member) - << Name << computeDeclContext(*SS, false) - << SS->getRange()); + // in C90, extension in C99, forbidden in C++). + if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) { + NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); + if (D) R.addDecl(D); + } + + // If this name wasn't predeclared and if this is not a function + // call, diagnose the problem. + if (R.empty()) { + if (!SS.isEmpty()) + return ExprError(Diag(NameLoc, diag::err_no_member) + << Name << computeDeclContext(SS, false) + << SS.getRange()); else if (Name.getNameKind() == DeclarationName::CXXOperatorName || Name.getNameKind() == DeclarationName::CXXConversionFunctionName) - return ExprError(Diag(Loc, diag::err_undeclared_use) - << Name.getAsString()); + return ExprError(Diag(NameLoc, diag::err_undeclared_use) + << Name); else - return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name); + return ExprError(Diag(NameLoc, diag::err_undeclared_var_use) << Name); } } - if (VarDecl *Var = Lookup.getAsSingle<VarDecl>()) { + // This is guaranteed from this point on. + assert(!R.empty() || ADL); + + if (VarDecl *Var = R.getAsSingle<VarDecl>()) { // Warn about constructs like: // if (void *X = foo()) { ... } else { X }. // In the else block, the pointer is always false. - // FIXME: In a template instantiation, we don't have scope - // information to check this property. if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) { Scope *CheckS = S; while (CheckS && CheckS->getControlParent()) { if (CheckS->isWithinElse() && CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { - ExprError(Diag(Loc, diag::warn_value_always_zero) + ExprError(Diag(NameLoc, diag::warn_value_always_zero) << Var->getDeclName() << (Var->getType()->isPointerType()? 2 : Var->getType()->isBooleanType()? 1 : 0)); @@ -823,21 +761,21 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, CheckS = CheckS->getParent(); } } - } else if (FunctionDecl *Func = Lookup.getAsSingle<FunctionDecl>()) { + } else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) { if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) { // C99 DR 316 says that, if a function type comes from a // function definition (without a prototype), that type is only // used for checking compatibility. Therefore, when referencing // the function, we pretend that we don't have the full function // type. - if (DiagnoseUseOfDecl(Func, Loc)) + if (DiagnoseUseOfDecl(Func, NameLoc)) return ExprError(); QualType T = Func->getType(); QualType NoProtoType = T; if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>()) NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); - return BuildDeclRefExpr(Func, NoProtoType, Loc, SS); + return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS); } } @@ -853,19 +791,141 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // calculate them both in one pass if that proves important for // performance. if (!ADL) { - bool isAbstractMemberPointer = - (isAddressOfOperand && SS && !SS->isEmpty()); + bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty()); + + if (!isAbstractMemberPointer && !R.empty() && + isa<CXXRecordDecl>((*R.begin())->getDeclContext())) { + return BuildImplicitMemberReferenceExpr(SS, R, TemplateArgs); + } + } + + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs); + + return BuildDeclarationNameExpr(SS, R, ADL); +} + +/// ActOnDeclarationNameExpr - Build a C++ qualified declaration name, +/// generally during template instantiation. There's a large number +/// of things which don't need to be done along this path. +Sema::OwningExprResult +Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || + DC->isDependentContext() || + RequireCompleteDeclContext(SS)) + return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0); + + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + LookupQualifiedName(R, DC); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameLoc, diag::err_no_member) << Name << DC << SS.getRange(); + return ExprError(); + } + + return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); +} + +/// LookupInObjCMethod - The parser has read a name in, and Sema has +/// detected that we're currently inside an ObjC method. Perform some +/// additional lookup. +/// +/// Ideally, most of this would be done by lookup, but there's +/// actually quite a lot of extra work involved. +/// +/// Returns a null sentinel to indicate trivial success. +Sema::OwningExprResult +Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II) { + SourceLocation Loc = Lookup.getNameLoc(); + + // There are two cases to handle here. 1) scoped lookup could have failed, + // in which case we should look for an ivar. 2) scoped lookup could have + // found a decl, but that decl is outside the current instance method (i.e. + // a global variable). In these two cases, we do a lookup for an ivar with + // this name, if the lookup sucedes, we replace it our current decl. + + // If we're in a class method, we don't normally want to look for + // ivars. But if we don't find anything else, and there's an + // ivar, that's an error. + bool IsClassMethod = getCurMethodDecl()->isClassMethod(); + + bool LookForIvars; + if (Lookup.empty()) + LookForIvars = true; + else if (IsClassMethod) + LookForIvars = false; + else + LookForIvars = (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + + if (LookForIvars) { + ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + // Diagnose using an ivar in a class method. + if (IsClassMethod) + return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) + << IV->getDeclName()); + + // If we're referencing an invalid decl, just return this as a silent + // error node. The error diagnostic was already emitted on the decl. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check if referencing a field with __attribute__((deprecated)). + if (DiagnoseUseOfDecl(IV, Loc)) + return ExprError(); - if (!isAbstractMemberPointer && !Lookup.empty() && - isa<CXXRecordDecl>((*Lookup.begin())->getDeclContext())) { - return BuildImplicitMemberReferenceExpr(SS, Lookup); + // Diagnose the use of an ivar outside of the declaring class. + if (IV->getAccessControl() == ObjCIvarDecl::Private && + ClassDeclared != IFace) + Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); + + // FIXME: This should use a new expr for a direct reference, don't + // turn this into Self->ivar, just return a BareIVarExpr or something. + IdentifierInfo &II = Context.Idents.get("self"); + UnqualifiedId SelfName; + SelfName.setIdentifier(&II, SourceLocation()); + CXXScopeSpec SelfScopeSpec; + OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, + SelfName, false, false); + MarkDeclarationReferenced(Loc, IV); + return Owned(new (Context) + ObjCIvarRefExpr(IV, IV->getType(), Loc, + SelfExpr.takeAs<Expr>(), true, true)); + } + } else if (getCurMethodDecl()->isInstanceMethod()) { + // We should warn if a local variable hides an ivar. + ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + if (IV->getAccessControl() != ObjCIvarDecl::Private || + IFace == ClassDeclared) + Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); } } - assert(Lookup.getResultKind() != LookupResult::FoundUnresolvedValue && - "found UnresolvedUsingValueDecl in non-class scope"); + // Needed to implement property "super.method" notation. + if (Lookup.empty() && II->isStr("super")) { + QualType T; + + if (getCurMethodDecl()->isInstanceMethod()) + T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType( + getCurMethodDecl()->getClassInterface())); + else + T = Context.getObjCClassType(); + return Owned(new (Context) ObjCSuperExpr(Loc, T)); + } - return BuildDeclarationNameExpr(SS, Lookup, ADL); + // Sentinel value saying that we didn't do anything special. + return Owned((Expr*) 0); } /// \brief Cast member's object to its own class if necessary. @@ -899,29 +959,35 @@ Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { /// \brief Build a MemberExpr AST node. static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, const CXXScopeSpec *SS, NamedDecl *Member, - SourceLocation Loc, QualType Ty) { - if (SS && SS->isSet()) - return MemberExpr::Create(C, Base, isArrow, - (NestedNameSpecifier *)SS->getScopeRep(), - SS->getRange(), Member, Loc, - // FIXME: Explicit template argument lists - 0, Ty); - - return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty); + SourceLocation Loc, QualType Ty, + const TemplateArgumentListInfo *TemplateArgs = 0) { + NestedNameSpecifier *Qualifier = 0; + SourceRange QualifierRange; + if (SS && SS->isSet()) { + Qualifier = (NestedNameSpecifier *) SS->getScopeRep(); + QualifierRange = SS->getRange(); + } + + return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange, + Member, Loc, TemplateArgs, Ty); } /// Builds an implicit member access expression from the given /// unqualified lookup set, which is known to contain only class /// members. Sema::OwningExprResult -Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS, - LookupResult &R) { +Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { + assert(!R.empty() && !R.isAmbiguous()); + NamedDecl *D = R.getAsSingleDecl(Context); SourceLocation Loc = R.getNameLoc(); // We may have found a field within an anonymous union or struct // (C++ [class.union]). // FIXME: This needs to happen post-isImplicitMemberReference? + // FIXME: template-ids inside anonymous structs? if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion()) return BuildAnonymousStructUnionMemberReference(Loc, FD); @@ -938,13 +1004,14 @@ Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS, if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { // Don't diagnose the use of a virtual member function unless it's // explicitly qualified. - if (MD->isVirtual() && (!SS || !SS->isSet())) + if (MD->isVirtual() && !SS.isSet()) ShouldCheckUse = false; } if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc)) return ExprError(); - return Owned(BuildMemberExpr(Context, This, true, SS, D, Loc, MemberType)); + return Owned(BuildMemberExpr(Context, This, true, &SS, D, Loc, MemberType, + TemplateArgs)); } if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { @@ -973,10 +1040,13 @@ Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS, // We're not in an implicit member-reference context, but the lookup // results might not require an instance. Try to build a non-member // decl reference. + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, /* ADL */ false, *TemplateArgs); + return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); } -bool Sema::UseArgumentDependentLookup(const CXXScopeSpec *SS, +bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, bool HasTrailingLParen) { // Only when used directly as the postfix-expression of a call. @@ -984,7 +1054,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec *SS, return false; // Never if a scope specifier was provided. - if (SS && SS->isSet()) + if (SS.isSet()) return false; // Only in C++ or ObjC++. @@ -1056,11 +1126,13 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { } Sema::OwningExprResult -Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL) { assert(R.getResultKind() != LookupResult::FoundUnresolvedValue); + // If this isn't an overloaded result and we don't need ADL, just + // build an ordinary singleton decl ref. if (!NeedsADL && !R.isOverloadedResult()) return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl()); @@ -1071,10 +1143,12 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) return ExprError(); + bool Dependent + = Unres |