зеркало из https://github.com/microsoft/clang-1.git
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) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63733 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
20bcd55e14
Коммит
17330019f0
|
@ -727,28 +727,35 @@ public:
|
|||
static CXXDeleteExpr * CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||
};
|
||||
|
||||
/// CXXDependentNameExpr - Represents a dependent name in C++ for
|
||||
/// which we could not locate any definition. These names can only
|
||||
/// occur as in the example below, with an unqualified call to a
|
||||
/// function name whose arguments are dependent.
|
||||
/// \brief Represents the name of a function that has not been
|
||||
/// resolved to any declaration.
|
||||
///
|
||||
/// Unresolved function names occur when a function name is
|
||||
/// encountered prior to an open parentheses ('(') in a C++ function
|
||||
/// call, and the function name itself did not resolve to a
|
||||
/// declaration. These function names can only be resolved when they
|
||||
/// form the postfix-expression of a function call, so that
|
||||
/// argument-dependent lookup finds declarations corresponding to
|
||||
/// these functions.
|
||||
|
||||
/// @code
|
||||
/// template<typename T> void f(T x) {
|
||||
/// g(x); // g is a dependent name.
|
||||
/// g(x); // g is an unresolved function name (that is also a dependent name)
|
||||
/// }
|
||||
/// @endcode
|
||||
class CXXDependentNameExpr : public Expr {
|
||||
/// Name - The name that was present in the source code.
|
||||
IdentifierInfo *Name;
|
||||
class UnresolvedFunctionNameExpr : public Expr {
|
||||
/// The name that was present in the source
|
||||
DeclarationName Name;
|
||||
|
||||
/// Loc - The location
|
||||
/// The location of this name in the source code
|
||||
SourceLocation Loc;
|
||||
|
||||
public:
|
||||
CXXDependentNameExpr(IdentifierInfo *N, QualType T, SourceLocation L)
|
||||
: Expr(CXXDependentNameExprClass, T, true, true), Name(N), Loc(L) { }
|
||||
UnresolvedFunctionNameExpr(DeclarationName N, QualType T, SourceLocation L)
|
||||
: Expr(UnresolvedFunctionNameExprClass, T, false, false), Name(N), Loc(L) { }
|
||||
|
||||
/// getName - Retrieves the name that occurred in the source code.
|
||||
IdentifierInfo *getName() const { return Name; }
|
||||
/// \brief Retrieves the name that occurred in the source code.
|
||||
DeclarationName getName() const { return Name; }
|
||||
|
||||
/// getLocation - Retrieves the location in the source code where
|
||||
/// the name occurred.
|
||||
|
@ -757,16 +764,16 @@ public:
|
|||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXDependentNameExprClass;
|
||||
return T->getStmtClass() == UnresolvedFunctionNameExprClass;
|
||||
}
|
||||
static bool classof(const CXXDependentNameExpr *) { return true; }
|
||||
static bool classof(const UnresolvedFunctionNameExpr *) { return true; }
|
||||
|
||||
// Iterators
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
|
||||
virtual void EmitImpl(llvm::Serializer& S) const;
|
||||
static CXXDependentNameExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||
static UnresolvedFunctionNameExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||
};
|
||||
|
||||
/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
|
||||
|
|
|
@ -115,7 +115,7 @@ STMT(CXXZeroInitValueExpr , Expr)
|
|||
STMT(CXXConditionDeclExpr , DeclRefExpr)
|
||||
STMT(CXXNewExpr , Expr)
|
||||
STMT(CXXDeleteExpr , Expr)
|
||||
STMT(CXXDependentNameExpr , Expr)
|
||||
STMT(UnresolvedFunctionNameExpr , Expr)
|
||||
STMT(UnaryTypeTraitExpr , Expr)
|
||||
STMT(QualifiedDeclRefExpr , DeclRefExpr)
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
// 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
|
||||
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));
|
||||
|
||||
// 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));
|
||||
DeclarationName UnqualifiedName;
|
||||
|
||||
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;
|
||||
|
||||
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 (Fn->getType()->isRecordType())
|
||||
return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
|
||||
CommaLocs, RParenLoc));
|
||||
|
||||
// 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,
|
||||
|
|
|
@ -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 ).
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace N {
|
|||
X operator+(X, X);
|
||||
|
||||
void f(X);
|
||||
void g(X);
|
||||
void g(X); // expected-note{{candidate function}}
|
||||
|
||||
void test_multiadd(X x) {
|
||||
(void)(x + x);
|
||||
|
@ -39,7 +39,22 @@ namespace N {
|
|||
|
||||
|
||||
void test_func_adl_only(N::X x) {
|
||||
// FIXME: here, despite the fact that the name lookup for 'g' fails,
|
||||
// this is well-formed code. The fix will go into Sema::ActOnCallExpr.
|
||||
// g(x);
|
||||
g(x);
|
||||
}
|
||||
|
||||
namespace M {
|
||||
int g(N::X); // expected-note{{candidate function}}
|
||||
|
||||
void test(N::X x) {
|
||||
g(x); // expected-error{{call to 'g' is ambiguous; candidates are:}}
|
||||
int i = (g)(x);
|
||||
|
||||
int g(N::X);
|
||||
g(x); // okay; calls locally-declared function, no ADL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_operator_name_adl(N::X x) {
|
||||
(void)operator+(x, x);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ public:
|
|||
}
|
||||
|
||||
float g() {
|
||||
return operator float(); // expected-error{{use of undeclared 'operator float'}}
|
||||
return operator float(); // expected-error{{no matching function for call to 'operator float'}}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,6 @@ T f(T x) {
|
|||
return g(x);
|
||||
h(x); // h is a dependent name
|
||||
g(1, 1); // expected-error{{no matching function for call}}
|
||||
h(1); // expected-error{{use of undeclared identifier 'h'}}
|
||||
h(1); // expected-error{{no matching function for call to 'h'}}
|
||||
return 0;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче