diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-09 08:00:36 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-09 08:00:36 +0000 |
commit | 36f5cfe4df32af6c5fe01228102512996f566f9d (patch) | |
tree | 28e2c2562f781f6dbe711d15a00af596b21b9c9b /lib/Sema/SemaOverload.cpp | |
parent | 8a26fc15d4647da863f0cca73a203823b01da7e5 (diff) |
Support for raw and template forms of numeric user-defined literals,
and lots of tidying up.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152392 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 121 |
1 files changed, 50 insertions, 71 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 14c773fdb4..e74e6d5e12 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5236,7 +5236,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, llvm::ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions) { + bool SuppressUserConversions, + TemplateArgumentListInfo *ExplicitTemplateArgs) { for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { NamedDecl *D = F.getDecl()->getUnderlyingDecl(); if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -5255,13 +5256,13 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) AddMethodTemplateCandidate(FunTmpl, F.getPair(), cast<CXXRecordDecl>(FunTmpl->getDeclContext()), - /*FIXME: explicit args */ 0, + ExplicitTemplateArgs, Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), CandidateSet, SuppressUserConversions); else AddTemplateOverloadCandidate(FunTmpl, F.getPair(), - /*FIXME: explicit args */ 0, Args, + ExplicitTemplateArgs, Args, CandidateSet, SuppressUserConversions); } } @@ -10895,66 +10896,60 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { return MaybeBindToTemporary(TheCall); } -static void FilterLookupForLiteralOperator(Sema &S, LookupResult &R, - ArrayRef<Expr*> Args) { - LookupResult::Filter F = R.makeFilter(); +/// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call to +/// a literal operator described by the provided lookup results. +ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, + DeclarationNameInfo &SuffixInfo, + ArrayRef<Expr*> Args, + SourceLocation LitEndLoc, + TemplateArgumentListInfo *TemplateArgs) { + SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc(); - while (F.hasNext()) { - FunctionDecl *D = dyn_cast<FunctionDecl>(F.next()); - // FIXME: using-decls? + OverloadCandidateSet CandidateSet(UDSuffixLoc); + AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true, + TemplateArgs); - if (!D || D->getNumParams() != Args.size()) { - F.erase(); - } else { - // The literal operator's parameter types must exactly match the decayed - // argument types. - for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { - QualType ArgTy = Args[ArgIdx]->getType(); - QualType ParamTy = D->getParamDecl(ArgIdx)->getType(); - if (ArgTy->isArrayType()) - ArgTy = S.Context.getArrayDecayedType(ArgTy); - if (!S.Context.hasSameUnqualifiedType(ArgTy, ParamTy)) { - F.erase(); - break; - } - } - } + bool HadMultipleCandidates = (CandidateSet.size() > 1); + + // FIXME: Reject default arguments in literal operator definitions. We're not + // supposed to treat this as ambiguous: + // + // int operator"" _x(const char *p); + // int operator"" _x(const char *p, size_t n = 0); + // int k = 123_x; + + // Perform overload resolution. This will usually be trivial, but might need + // to perform substitutions for a literal operator template. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, UDSuffixLoc, Best)) { + case OR_Success: + case OR_Deleted: + break; + + case OR_No_Viable_Function: + Diag(UDSuffixLoc, diag::err_ovl_no_viable_function_in_call) + << R.getLookupName(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + return ExprError(); + + case OR_Ambiguous: + Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args); + return ExprError(); } - F.done(); -} + FunctionDecl *FD = Best->Function; + MarkFunctionReferenced(UDSuffixLoc, FD); + DiagnoseUseOfDecl(Best->FoundDecl, UDSuffixLoc); -/// BuildLiteralOperatorCall - A user-defined literal was found. Look up the -/// corresponding literal operator, and build a call to it. -/// FIXME: Support for raw literal operators and literal operator templates. -ExprResult -Sema::BuildLiteralOperatorCall(IdentifierInfo *UDSuffix, - SourceLocation UDSuffixLoc, - ArrayRef<Expr*> Args, SourceLocation LitEndLoc) { - DeclarationName OpName = - Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix); - DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); - OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); - - LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName); - LookupName(R, /*FIXME*/CurScope); - assert(R.getResultKind() != LookupResult::Ambiguous && - "literal operator lookup can't be ambiguous"); - - // Filter the lookup results appropriately. - FilterLookupForLiteralOperator(*this, R, Args); - - // FIXME: For literal operator templates, we need to perform overload - // resolution to deal with SFINAE. - FunctionDecl *FD = R.getAsSingle<FunctionDecl>(); - if (!FD || FD->getNumParams() != Args.size()) - return ExprError( - Diag(UDSuffixLoc, diag::err_ovl_no_viable_oper) << UDSuffix->getName()); - bool HadMultipleCandidates = false; + ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates, + SuffixInfo.getLoc(), + SuffixInfo.getInfo()); + if (Fn.isInvalid()) + return true; // Check the argument types. This should almost always be a no-op, except // that array-to-pointer decay is applied to string literals. - assert(Args.size() <= 2 && "too many arguments for literal operator"); Expr *ConvArgs[2]; for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { ExprResult InputInit = PerformCopyInitialization( @@ -10965,26 +10960,10 @@ Sema::BuildLiteralOperatorCall(IdentifierInfo *UDSuffix, ConvArgs[ArgIdx] = InputInit.take(); } - MarkFunctionReferenced(UDSuffixLoc, FD); - DiagnoseUseOfDecl(FD, UDSuffixLoc); - - ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates, - OpNameInfo.getLoc(), - OpNameInfo.getInfo()); - if (Fn.isInvalid()) - return true; - QualType ResultTy = FD->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultTy); ResultTy = ResultTy.getNonLValueExprType(Context); - // FIXME: A literal operator call never uses default arguments. - // But is this ambiguous? - // void operator"" _x(const char *p); - // void operator"" _x(const char *p, size_t n = 0); - // 123_x - // g++ says no, but bizarrely rejects it if the default argument is omitted. - UserDefinedLiteral *UDL = new (Context) UserDefinedLiteral(Context, Fn.take(), ConvArgs, Args.size(), ResultTy, VK, LitEndLoc, UDSuffixLoc); |