aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-03-09 08:00:36 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-03-09 08:00:36 +0000
commit36f5cfe4df32af6c5fe01228102512996f566f9d (patch)
tree28e2c2562f781f6dbe711d15a00af596b21b9c9b /lib/Sema/SemaOverload.cpp
parent8a26fc15d4647da863f0cca73a203823b01da7e5 (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.cpp121
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);