diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-04 15:01:18 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-04 15:01:18 +0000 |
commit | b8a9a41dd6ea0b0d652edb5be0a78dd21e0e271d (patch) | |
tree | 73af2a895cd623e0261648fcb2cb3d7c31e9c9ee /clang/lib | |
parent | 82b7372941c4273d0bc4180b2b60c681fbcf63d1 (diff) | |
download | bcm5719-llvm-b8a9a41dd6ea0b0d652edb5be0a78dd21e0e271d.tar.gz bcm5719-llvm-b8a9a41dd6ea0b0d652edb5be0a78dd21e0e271d.zip |
Fix our semantic analysis of
unqualified-id '('
in C++. The unqualified-id might not refer to any declaration in our
current scope, but declarations by that name might be found via
argument-dependent lookup. We now do so properly.
As part of this change, CXXDependentNameExpr, which was previously
designed to express the unqualified-id in the above constructor within
templates, has become UnresolvedFunctionNameExpr, which does
effectively the same thing but will work for both templates and
non-templates.
Additionally, we cope with all unqualified-ids, since ADL also applies
in cases like
operator+(x, y)
llvm-svn: 63733
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/StmtSerialization.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 131 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 54 |
7 files changed, 119 insertions, 100 deletions
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index b21b4136898..dbc811a68b1 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -120,11 +120,11 @@ Stmt::child_iterator CXXNewExpr::child_end() { Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; } Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; } -// CXXDependentNameExpr -Stmt::child_iterator CXXDependentNameExpr::child_begin() { +// UnresolvedFunctionNameExpr +Stmt::child_iterator UnresolvedFunctionNameExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator CXXDependentNameExpr::child_end() { +Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() { return child_iterator(); } diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 27bab206a4e..1f07db76925 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1101,8 +1101,8 @@ void StmtPrinter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { PrintExpr(E->getArgument()); } -void StmtPrinter::VisitCXXDependentNameExpr(CXXDependentNameExpr *E) { - OS << E->getName()->getName(); +void StmtPrinter::VisitUnresolvedFunctionNameExpr(UnresolvedFunctionNameExpr *E) { + OS << E->getName().getAsString(); } static const char *getTypeTraitName(UnaryTypeTrait UTT) { diff --git a/clang/lib/AST/StmtSerialization.cpp b/clang/lib/AST/StmtSerialization.cpp index 8599a7aba90..3bb98b46f49 100644 --- a/clang/lib/AST/StmtSerialization.cpp +++ b/clang/lib/AST/StmtSerialization.cpp @@ -245,8 +245,8 @@ Stmt* Stmt::Create(Deserializer& D, ASTContext& C) { case CXXDeleteExprClass: return CXXDeleteExpr::CreateImpl(D, C); - case CXXDependentNameExprClass: - return CXXDependentNameExpr::CreateImpl(D, C); + case UnresolvedFunctionNameExprClass: + return UnresolvedFunctionNameExpr::CreateImpl(D, C); case CXXCatchStmtClass: return CXXCatchStmt::CreateImpl(D, C); @@ -1528,18 +1528,18 @@ CXXDeleteExpr::CreateImpl(Deserializer& D, ASTContext& C) { cast<Expr>(Argument), Loc); } -void CXXDependentNameExpr::EmitImpl(llvm::Serializer& S) const { +void UnresolvedFunctionNameExpr::EmitImpl(llvm::Serializer& S) const { S.Emit(getType()); - S.EmitPtr(Name); + S.EmitPtr(Name.getAsIdentifierInfo()); // FIXME: WRONG! S.Emit(Loc); } -CXXDependentNameExpr * -CXXDependentNameExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) { +UnresolvedFunctionNameExpr * +UnresolvedFunctionNameExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) { QualType Ty = QualType::ReadVal(D); IdentifierInfo *N = D.ReadPtr<IdentifierInfo>(); SourceLocation L = SourceLocation::ReadVal(D); - return new CXXDependentNameExpr(N, Ty, L); + return new UnresolvedFunctionNameExpr(N, Ty, L); } void UnaryTypeTraitExpr::EmitImpl(llvm::Serializer& S) const { diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3143b5c4829..6b8d852db39 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -517,12 +517,13 @@ public: bool Complain); void FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); - FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Func, + FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, + DeclarationName UnqualifiedName, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc, - bool ArgumentDependentLookup); + bool &ArgumentDependentLookup); ExprResult BuildCallToMemberFunction(Scope *S, Expr *MemExpr, SourceLocation LParenLoc, Expr **Args, @@ -1068,7 +1069,6 @@ public: DeclarationName Name, bool HasTrailingLParen, const CXXScopeSpec *SS, - bool ForceResolution = false, bool isAddressOfOperand = false); virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 24f7965b63c..c1e4c0ecdd4 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -366,7 +366,7 @@ Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, const CXXScopeSpec *SS, bool isAddressOfOperand) { return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS, - /*ForceResolution*/false, isAddressOfOperand); + isAddressOfOperand); } /// BuildDeclRefExpr - Build either a DeclRefExpr or a @@ -535,10 +535,6 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, /// qualified-id (foo::bar) to indicate the class or namespace that /// the identifier must be a member of. /// -/// If ForceResolution is true, then we will attempt to resolve the -/// name even if it looks like a dependent name. This option is off by -/// default. -/// /// 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 @@ -546,27 +542,27 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, Sema::OwningExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, DeclarationName Name, bool HasTrailingLParen, - const CXXScopeSpec *SS, bool ForceResolution, + const CXXScopeSpec *SS, bool isAddressOfOperand) { - if (S->getTemplateParamParent() && Name.getAsIdentifierInfo() && - HasTrailingLParen && !SS && !ForceResolution) { - // We've seen something of the form - // identifier( - // and we are in a template, so it is likely that 's' is a - // dependent name. However, we won't know until we've parsed all - // of the call arguments. So, build a CXXDependentNameExpr node - // to represent this name. Then, if it turns out that none of the - // arguments are type-dependent, we'll force the resolution of the - // dependent name at that point. - return Owned(new (Context) CXXDependentNameExpr(Name.getAsIdentifierInfo(), - Context.DependentTy, Loc)); - } - // Could be enum-constant, value decl, instance variable, etc. if (SS && SS->isInvalid()) return ExprError(); LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName); + if (getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && + HasTrailingLParen && Lookup.getKind() == LookupResult::NotFound) { + // We've seen something of the form + // + // identifier( + // + // and we did not find any entity by the name + // "identifier". However, this identifier is still subject to + // argument-dependent lookup, so keep track of the name. + return Owned(new (Context) UnresolvedFunctionNameExpr(Name, + Context.OverloadTy, + Loc)); + } + Decl *D = 0; if (Lookup.isAmbiguous()) { DiagnoseAmbiguousLookup(Lookup, Name, Loc, @@ -1839,48 +1835,27 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, Expr **Args = reinterpret_cast<Expr**>(args.release()); assert(Fn && "no function call expression"); FunctionDecl *FDecl = NULL; + DeclarationName UnqualifiedName; - // Determine whether this is a dependent call inside a C++ template, - // in which case we won't do any semantic analysis now. - bool Dependent = false; - if (Fn->isTypeDependent()) { - if (CXXDependentNameExpr *FnName = dyn_cast<CXXDependentNameExpr>(Fn)) { - if (Expr::hasAnyTypeDependentArguments(Args, NumArgs)) - Dependent = true; - else { - // Resolve the CXXDependentNameExpr to an actual identifier; - // it wasn't really a dependent name after all. - // FIXME: in the presence of ADL, this resolves too early. - OwningExprResult Resolved - = ActOnDeclarationNameExpr(S, FnName->getLocation(), - FnName->getName(), - /*HasTrailingLParen=*/true, - /*SS=*/0, - /*ForceResolution=*/true); - if (Resolved.isInvalid()) - return ExprError(); - else { - delete Fn; - Fn = (Expr *)Resolved.release(); - } - } - } else + if (getLangOptions().CPlusPlus) { + // Determine whether this is a dependent call inside a C++ template, + // in which case we won't do any semantic analysis now. + // FIXME: Will need to cache the results of name lookup (including ADL) in Fn. + bool Dependent = false; + if (Fn->isTypeDependent()) + Dependent = true; + else if (Expr::hasAnyTypeDependentArguments(Args, NumArgs)) Dependent = true; - } else - Dependent = Expr::hasAnyTypeDependentArguments(Args, NumArgs); - // FIXME: Will need to cache the results of name lookup (including - // ADL) in Fn. - if (Dependent) - return Owned(new (Context) CallExpr(Fn, Args, NumArgs, - Context.DependentTy, RParenLoc)); + if (Dependent) + return Owned(new (Context) CallExpr(Fn, Args, NumArgs, + Context.DependentTy, RParenLoc)); - // Determine whether this is a call to an object (C++ [over.call.object]). - if (getLangOptions().CPlusPlus && Fn->getType()->isRecordType()) - return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, - CommaLocs, RParenLoc)); + // Determine whether this is a call to an object (C++ [over.call.object]). + if (Fn->getType()->isRecordType()) + return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, + CommaLocs, RParenLoc)); - if (getLangOptions().CPlusPlus) { // Determine whether this is a call to a member function. if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens())) if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) || @@ -1897,7 +1872,8 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) FnExpr = IcExpr->getSubExpr(); else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { - // FIXME: Where does the C++ standard say this? + // Parentheses around a function disable ADL + // (C++0x [basic.lookup.argdep]p1). ADL = false; FnExpr = PExpr->getSubExpr(); } else if (isa<UnaryOperator>(FnExpr) && @@ -1905,32 +1881,39 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, == UnaryOperator::AddrOf) { FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); } else { - DRExpr = dyn_cast<DeclRefExpr>(FnExpr); + if (isa<DeclRefExpr>(FnExpr)) { + DRExpr = cast<DeclRefExpr>(FnExpr); + + // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). + ADL = ADL && !isa<QualifiedDeclRefExpr>(DRExpr); + } + else if (UnresolvedFunctionNameExpr *DepName + = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) + UnqualifiedName = DepName->getName(); + else { + // Any kind of name that does not refer to a declaration (or + // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). + ADL = false; + } break; } } - if (DRExpr) + OverloadedFunctionDecl *Ovl = 0; + if (DRExpr) { FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()); + Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl()); + } - if (getLangOptions().CPlusPlus && DRExpr && - (FDecl || isa<OverloadedFunctionDecl>(DRExpr->getDecl()))) { - // C++ [basic.lookup.argdep]p1: - // When an unqualified name is used as the postfix-expression in - // a function call (5.2.2), other namespaces not considered - // during the usual unqualified lookup (3.4.1) may be searched, - // and namespace-scope friend func- tion declarations (11.4) not - // otherwise visible may be found. - if (DRExpr && isa<QualifiedDeclRefExpr>(DRExpr)) - ADL = false; - + if (getLangOptions().CPlusPlus && (FDecl || Ovl || UnqualifiedName)) { // We don't perform ADL for builtins. if (FDecl && FDecl->getIdentifier() && FDecl->getIdentifier()->getBuiltinID()) ADL = false; - if ((DRExpr && isa<OverloadedFunctionDecl>(DRExpr->getDecl())) || ADL) { - FDecl = ResolveOverloadedCallFn(Fn, DRExpr->getDecl(), LParenLoc, Args, + if (Ovl || ADL) { + FDecl = ResolveOverloadedCallFn(Fn, DRExpr? DRExpr->getDecl() : 0, + UnqualifiedName, LParenLoc, Args, NumArgs, CommaLocs, RParenLoc, ADL); if (!FDecl) return ExprError(); @@ -1938,7 +1921,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // Update Fn to refer to the actual function selected. Expr *NewFn = 0; if (QualifiedDeclRefExpr *QDRExpr - = dyn_cast<QualifiedDeclRefExpr>(DRExpr)) + = dyn_cast_or_null<QualifiedDeclRefExpr>(DRExpr)) NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(), QDRExpr->getLocation(), false, false, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e9dbc849b00..2a7c9a85f00 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -35,7 +35,7 @@ Sema::ActOnCXXConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc, DeclarationName ConvName = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon); return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen, - &SS, /*ForceRes*/false, isAddressOfOperand); + &SS, isAddressOfOperand); } /// ActOnCXXOperatorFunctionIdExpr - Parse a C++ overloaded operator @@ -51,7 +51,7 @@ Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc, bool isAddressOfOperand) { DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op); return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS, - /*ForceRes*/false, isAddressOfOperand); + isAddressOfOperand); } /// ActOnCXXTypeidOfType - Parse typeid( type-id ). diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 293e9c3c24b..01b9829c665 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3503,20 +3503,56 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, /// resolution. Otherwise, emits diagnostics, deletes all of the /// arguments and Fn, and returns NULL. FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, + DeclarationName UnqualifiedName, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc, - bool ArgumentDependentLookup) { + bool &ArgumentDependentLookup) { OverloadCandidateSet CandidateSet; + + // Add the functions denoted by Callee to the set of candidate + // functions. While we're doing so, track whether argument-dependent + // lookup still applies, per: + // + // C++0x [basic.lookup.argdep]p3: + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains + // + // -- a declaration of a class member, or + // + // -- a block-scope function declaration that is not a + // using-declaration, or + // + // -- a declaration that is neither a function or a function + // template + // + // then Y is empty. if (OverloadedFunctionDecl *Ovl - = dyn_cast_or_null<OverloadedFunctionDecl>(Callee)) - AddOverloadCandidates(Ovl, Args, NumArgs, CandidateSet); - else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) - AddOverloadCandidate(cast<FunctionDecl>(Func), Args, NumArgs, CandidateSet); - + = dyn_cast_or_null<OverloadedFunctionDecl>(Callee)) { + for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), + FuncEnd = Ovl->function_end(); + Func != FuncEnd; ++Func) { + AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet); + + if ((*Func)->getDeclContext()->isRecord() || + (*Func)->getDeclContext()->isFunctionOrMethod()) + ArgumentDependentLookup = false; + } + } else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) { + AddOverloadCandidate(Func, Args, NumArgs, CandidateSet); + + if (Func->getDeclContext()->isRecord() || + Func->getDeclContext()->isFunctionOrMethod()) + ArgumentDependentLookup = false; + } + + if (Callee) + UnqualifiedName = Callee->getDeclName(); + if (ArgumentDependentLookup) - AddArgumentDependentLookupCandidates(Callee->getDeclName(), Args, NumArgs, + AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs, CandidateSet); OverloadCandidateSet::iterator Best; @@ -3527,14 +3563,14 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, case OR_No_Viable_Function: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_no_viable_function_in_call) - << Callee->getDeclName() << (unsigned)CandidateSet.size() + << UnqualifiedName << (unsigned)CandidateSet.size() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); break; case OR_Ambiguous: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) - << Callee->getDeclName() << Fn->getSourceRange(); + << UnqualifiedName << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; } |