diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 140 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 99 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 121 |
4 files changed, 273 insertions, 95 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 221cc6e53e..4d7310a146 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -9306,9 +9306,15 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { bool Valid = false; + // This might be the definition of a literal operator template. + FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate(); + // This might be a specialization of a literal operator template. + if (!TpDecl) + TpDecl = FnDecl->getPrimaryTemplate(); + // template <char...> type operator "" name() is the only valid template // signature, and the only valid signature with no parameters. - if (FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate()) { + if (TpDecl) { if (FnDecl->param_size() == 0) { // Must have only one template parameter TemplateParameterList *Params = TpDecl->getTemplateParameters(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 64008e1093..2adce06ce0 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1130,6 +1130,35 @@ static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc, S.getLangOptions()); } +/// BuildCookedLiteralOperatorCall - A user-defined literal was found. Look up +/// the corresponding cooked (non-raw) literal operator, and build a call to it. +static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope, + IdentifierInfo *UDSuffix, + SourceLocation UDSuffixLoc, + ArrayRef<Expr*> Args, + SourceLocation LitEndLoc) { + assert(Args.size() <= 2 && "too many arguments for literal operator"); + + QualType ArgTy[2]; + for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) { + ArgTy[ArgIdx] = Args[ArgIdx]->getType(); + if (ArgTy[ArgIdx]->isArrayType()) + ArgTy[ArgIdx] = S.Context.getArrayDecayedType(ArgTy[ArgIdx]); + } + + DeclarationName OpName = + S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix); + DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); + OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); + + LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName); + if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()), + /*AllowRawAndTemplate*/false) == Sema::LOLR_Error) + return ExprError(); + + return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc); +} + /// ActOnStringLiteral - The specified tokens were lexed as pasted string /// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string /// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from @@ -1137,7 +1166,8 @@ static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc, /// string. /// ExprResult -Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { +Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks, + Scope *UDLScope) { assert(NumStringToks && "Must have at least one string!"); StringLiteralParser Literal(StringToks, NumStringToks, PP); @@ -1193,6 +1223,10 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()], Literal.getUDSuffixOffset()); + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_string_udl)); + // C++11 [lex.ext]p5: The literal L is treated as a call of the form // operator "" X (str, len) QualType SizeType = Context.getSizeType(); @@ -1200,8 +1234,8 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType, StringTokLocs[0]); Expr *Args[] = { Lit, LenArg }; - return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc, Args, - StringTokLocs.back()); + return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc, + Args, StringTokLocs.back()); } ExprResult @@ -2381,7 +2415,7 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); } -ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { +ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) { SmallString<16> CharBuffer; bool Invalid = false; StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid); @@ -2424,11 +2458,15 @@ ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { SourceLocation UDSuffixLoc = getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset()); + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_character_udl)); + // C++11 [lex.ext]p6: The literal L is treated as a call of the form // operator "" X (ch) - return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc, - llvm::makeArrayRef(&Lit, 1), - Tok.getLocation()); + return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc, + llvm::makeArrayRef(&Lit, 1), + Tok.getLocation()); } ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) { @@ -2469,9 +2507,9 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc); } -ExprResult Sema::ActOnNumericConstant(const Token &Tok) { +ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // Fast path for a single digit (which is quite common). A single digit - // cannot have a trigraph, escaped newline, radix prefix, or type suffix. + // cannot have a trigraph, escaped newline, radix prefix, or suffix. if (Tok.getLength() == 1) { const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok); return ActOnIntegerConstant(Tok.getLocation(), Val-'0'); @@ -2499,32 +2537,88 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { SourceLocation UDSuffixLoc = getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset()); - // FIXME: Perform literal operator lookup now, and build a raw literal if - // there is no usable operator. + // Make sure we're allowed user-defined literals here. + if (!UDLScope) + return ExprError(Diag(UDSuffixLoc, diag::err_invalid_numeric_udl)); - QualType Ty; - Expr *Lit; + QualType CookedTy; if (Literal.isFloatingLiteral()) { // C++11 [lex.ext]p4: If S contains a literal operator with parameter type // long double, the literal is treated as a call of the form // operator "" X (f L) - Lit = BuildFloatingLiteral(*this, Literal, Context.LongDoubleTy, - Tok.getLocation()); + CookedTy = Context.LongDoubleTy; } else { // C++11 [lex.ext]p3: If S contains a literal operator with parameter type // unsigned long long, the literal is treated as a call of the form // operator "" X (n ULL) - llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0); - if (Literal.GetIntegerValue(ResultVal)) - Diag(Tok.getLocation(), diag::warn_integer_too_large); + CookedTy = Context.UnsignedLongLongTy; + } + + DeclarationName OpName = + Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix); + DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc); + OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc); + + // Perform literal operator lookup to determine if we're building a raw + // literal or a cooked one. + LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName); + switch (LookupLiteralOperator(UDLScope, R, llvm::makeArrayRef(&CookedTy, 1), + /*AllowRawAndTemplate*/true)) { + case LOLR_Error: + return ExprError(); - QualType Ty = Context.UnsignedLongLongTy; - Lit = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation()); + case LOLR_Cooked: { + Expr *Lit; + if (Literal.isFloatingLiteral()) { + Lit = BuildFloatingLiteral(*this, Literal, CookedTy, Tok.getLocation()); + } else { + llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0); + if (Literal.GetIntegerValue(ResultVal)) + Diag(Tok.getLocation(), diag::warn_integer_too_large); + Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy, + Tok.getLocation()); + } + return BuildLiteralOperatorCall(R, OpNameInfo, + llvm::makeArrayRef(&Lit, 1), + Tok.getLocation()); + } + + case LOLR_Raw: { + // C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the + // literal is treated as a call of the form + // operator "" X ("n") + SourceLocation TokLoc = Tok.getLocation(); + unsigned Length = Literal.getUDSuffixOffset(); + QualType StrTy = Context.getConstantArrayType( + Context.CharTy, llvm::APInt(32, Length + 1), + ArrayType::Normal, 0); + Expr *Lit = StringLiteral::Create( + Context, StringRef(ThisTokBegin, Length), StringLiteral::Ascii, + /*Pascal*/false, StrTy, &TokLoc, 1); + return BuildLiteralOperatorCall(R, OpNameInfo, + llvm::makeArrayRef(&Lit, 1), TokLoc); + } + + case LOLR_Template: + // C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator + // template), L is treated as a call fo the form + // operator "" X <'c1', 'c2', ... 'ck'>() + // where n is the source character sequence c1 c2 ... ck. + TemplateArgumentListInfo ExplicitArgs; + unsigned CharBits = Context.getIntWidth(Context.CharTy); + bool CharIsUnsigned = Context.CharTy->isUnsignedIntegerType(); + llvm::APSInt Value(CharBits, CharIsUnsigned); + for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) { + Value = ThisTokBegin[I]; + TemplateArgument Arg(Value, Context.CharTy); + TemplateArgumentLocInfo ArgInfo; + ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); + } + return BuildLiteralOperatorCall(R, OpNameInfo, ArrayRef<Expr*>(), + Tok.getLocation(), &ExplicitArgs); } - return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc, - llvm::makeArrayRef(&Lit, 1), - Tok.getLocation()); + llvm_unreachable("unexpected literal operator lookup result"); } Expr *Res; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 40774e135c..8e950ac207 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2525,6 +2525,105 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { false, false)->getMethod()); } +/// LookupLiteralOperator - Determine which literal operator should be used for +/// a user-defined literal, per C++11 [lex.ext]. +/// +/// Normal overload resolution is not used to select which literal operator to +/// call for a user-defined literal. Look up the provided literal operator name, +/// and filter the results to the appropriate set for the given argument types. +Sema::LiteralOperatorLookupResult +Sema::LookupLiteralOperator(Scope *S, LookupResult &R, + ArrayRef<QualType> ArgTys, + bool AllowRawAndTemplate) { + LookupName(R, S); + assert(R.getResultKind() != LookupResult::Ambiguous && + "literal operator lookup can't be ambiguous"); + + // Filter the lookup results appropriately. + LookupResult::Filter F = R.makeFilter(); + + bool FoundTemplate = false; + bool FoundRaw = false; + bool FoundExactMatch = false; + + while (F.hasNext()) { + Decl *D = F.next(); + if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) + D = USD->getTargetDecl(); + + bool IsTemplate = isa<FunctionTemplateDecl>(D); + bool IsRaw = false; + bool IsExactMatch = false; + + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->getNumParams() == 1 && + FD->getParamDecl(0)->getType()->getAs<PointerType>()) + IsRaw = true; + else { + IsExactMatch = true; + for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) { + QualType ParamTy = FD->getParamDecl(ArgIdx)->getType(); + if (!Context.hasSameUnqualifiedType(ArgTys[ArgIdx], ParamTy)) { + IsExactMatch = false; + break; + } + } + } + } + + if (IsExactMatch) { + FoundExactMatch = true; + AllowRawAndTemplate = false; + if (FoundRaw || FoundTemplate) { + // Go through again and remove the raw and template decls we've + // already found. + F.restart(); + FoundRaw = FoundTemplate = false; + } + } else if (AllowRawAndTemplate && (IsTemplate || IsRaw)) { + FoundTemplate |= IsTemplate; + FoundRaw |= IsRaw; + } else { + F.erase(); + } + } + + F.done(); + + // C++11 [lex.ext]p3, p4: If S contains a literal operator with a matching + // parameter type, that is used in preference to a raw literal operator + // or literal operator template. + if (FoundExactMatch) + return LOLR_Cooked; + + // C++11 [lex.ext]p3, p4: S shall contain a raw literal operator or a literal + // operator template, but not both. + if (FoundRaw && FoundTemplate) { + Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + Decl *D = *I; + if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) + D = USD->getTargetDecl(); + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) + D = FunTmpl->getTemplatedDecl(); + NoteOverloadCandidate(cast<FunctionDecl>(D)); + } + return LOLR_Error; + } + + if (FoundRaw) + return LOLR_Raw; + + if (FoundTemplate) + return LOLR_Template; + + // Didn't find anything we could use. + Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) + << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] + << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRawAndTemplate; + return LOLR_Error; +} + void ADLResult::insert(NamedDecl *New) { NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())]; 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); |