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/SemaExpr.cpp | |
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/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 506 |
1 files changed, 268 insertions, 238 deletions
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 + = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0); UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, - SS ? (NestedNameSpecifier *)SS->getScopeRep() : 0, - SS ? SS->getRange() : SourceRange(), + = UnresolvedLookupExpr::Create(Context, Dependent, + (NestedNameSpecifier*) SS.getScopeRep(), + SS.getRange(), R.getLookupName(), R.getNameLoc(), NeedsADL, R.isOverloadedResult()); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) @@ -1086,7 +1160,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, /// \brief Complete semantic analysis for a reference to the given declaration. Sema::OwningExprResult -Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, SourceLocation Loc, NamedDecl *D) { assert(D && "Cannot refer to a NULL declaration"); assert(!isa<FunctionTemplateDecl>(D) && @@ -1134,7 +1208,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS, // If this reference is not in a block or if the referenced variable is // within the block, create a normal DeclRefExpr. - return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, SS); + return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, &SS); } Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, @@ -2640,14 +2714,10 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, Name = DeclarationName(); Qualifier = 0; QualifierRange = SourceRange(); - ArgumentDependentLookup = getLangOptions().CPlusPlus; + ArgumentDependentLookup = false; Overloaded = false; HasExplicitTemplateArguments = false; - // Most of the explicit tracking of ArgumentDependentLookup in this - // function can disappear when we handle unresolved - // TemplateIdRefExprs properly. - // If we're directly calling a function, get the appropriate declaration. // Also, in C++, keep track of whether we should perform argument-dependent // lookup and whether there were any explicitly-specified template arguments. @@ -2655,9 +2725,6 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) FnExpr = IcExpr->getSubExpr(); else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { - // Parentheses around a function disable ADL - // (C++0x [basic.lookup.argdep]p1). - ArgumentDependentLookup = false; FnExpr = PExpr->getSubExpr(); } else if (isa<UnaryOperator>(FnExpr) && cast<UnaryOperator>(FnExpr)->getOpcode() @@ -2677,49 +2744,12 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, Overloaded = UnresLookup->isOverloaded(); if ((Qualifier = UnresLookup->getQualifier())) QualifierRange = UnresLookup->getQualifierRange(); - break; - } else if (TemplateIdRefExpr *TemplateIdRef - = dyn_cast<TemplateIdRefExpr>(FnExpr)) { - if (NamedDecl *Function - = TemplateIdRef->getTemplateName().getAsTemplateDecl()) { - Name = Function->getDeclName(); - Fns.push_back(Function); - } - else { - OverloadedFunctionDecl *Overload - = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl(); - Name = Overload->getDeclName(); - Fns.append(Overload->function_begin(), Overload->function_end()); - } - Overloaded = true; - HasExplicitTemplateArguments = true; - TemplateIdRef->copyTemplateArgumentsInto(ExplicitTemplateArgs); - - // C++ [temp.arg.explicit]p6: - // [Note: For simple function names, argument dependent lookup (3.4.2) - // applies even when the function name is not visible within the - // scope of the call. This is because the call still has the syntactic - // form of a function call (3.4.1). But when a function template with - // explicit template arguments is used, the call does not have the - // correct syntactic form unless there is a function template with - // that name visible at the point of the call. If no such name is - // visible, the call is not syntactically well-formed and - // argument-dependent lookup does not apply. If some such name is - // visible, argument dependent lookup applies and additional function - // templates may be found in other namespaces. - // - // The summary of this paragraph is that, if we get to this point and the - // template-id was not a qualified name, then argument-dependent lookup - // is still possible. - if ((Qualifier = TemplateIdRef->getQualifier())) { - ArgumentDependentLookup = false; - QualifierRange = TemplateIdRef->getQualifierRange(); + if (UnresLookup->hasExplicitTemplateArgs()) { + HasExplicitTemplateArguments = true; + UnresLookup->copyTemplateArgumentsInto(ExplicitTemplateArgs); } break; } else { - // Any kind of name that does not refer to a declaration (or - // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). - ArgumentDependentLookup = false; break; } } |