diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Expr.cpp | 6 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 33 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 3 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 25 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 4 | ||||
-rw-r--r-- | lib/Analysis/CFG.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 103 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 6 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 9 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 1 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 6 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 3 |
16 files changed, 221 insertions, 7 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index e35091a101..0fdca5a33b 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1681,7 +1681,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // Fallthrough for generic call handling. } case CallExprClass: - case CXXMemberCallExprClass: { + case CXXMemberCallExprClass: + case UserDefinedLiteralClass: { // If this is a direct call, get the callee. const CallExpr *CE = cast<CallExpr>(this); if (const Decl *FD = CE->getCalleeDecl()) { @@ -2014,7 +2015,8 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { // exception-specification case CallExprClass: case CXXMemberCallExprClass: - case CXXOperatorCallExprClass: { + case CXXOperatorCallExprClass: + case UserDefinedLiteralClass: { const CallExpr *CE = cast<CallExpr>(this); CanThrowResult CT; if (isTypeDependent()) diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index dc559f0940..039d70cfc5 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -624,6 +624,39 @@ CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) { return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize); } +UserDefinedLiteral::LiteralOperatorKind +UserDefinedLiteral::getLiteralOperatorKind() const { + if (getNumArgs() == 0) + return LOK_Template; + if (getNumArgs() == 2) + return LOK_String; + + assert(getNumArgs() == 1 && "unexpected #args in literal operator call"); + QualType ParamTy = + cast<FunctionDecl>(getCalleeDecl())->getParamDecl(0)->getType(); + if (ParamTy->isPointerType()) + return LOK_Raw; + if (ParamTy->isAnyCharacterType()) + return LOK_Character; + if (ParamTy->isIntegerType()) + return LOK_Integer; + if (ParamTy->isFloatingType()) + return LOK_Floating; + + llvm_unreachable("unknown kind of literal operator"); +} + +Expr *UserDefinedLiteral::getCookedLiteral() { +#ifndef NDEBUG + LiteralOperatorKind LOK = getLiteralOperatorKind(); + assert(LOK != LOK_Template && LOK != LOK_Raw && "not a cooked literal"); +#endif + return getArg(0); +} + +const IdentifierInfo *UserDefinedLiteral::getUDSuffix() const { + return cast<FunctionDecl>(getCalleeDecl())->getLiteralIdentifier(); +} CXXDefaultArgExpr * CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc, diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 693e28c8a4..00160a0073 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -269,6 +269,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: case Expr::CXXMemberCallExprClass: + case Expr::UserDefinedLiteralClass: case Expr::CUDAKernelCallExprClass: return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType()); diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 08794f355f..947f661c2c 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -6243,6 +6243,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: case Expr::CXXNullPtrLiteralExprClass: + case Expr::UserDefinedLiteralClass: case Expr::CXXThisExprClass: case Expr::CXXThrowExprClass: case Expr::CXXNewExprClass: diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index ea6e8b2e23..c4eed7c34d 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2439,6 +2439,9 @@ recurse: Arity); break; + case Expr::UserDefinedLiteralClass: + // We follow g++'s approach of mangling a UDL as a call to the literal + // operator. case Expr::CXXMemberCallExprClass: // fallthrough case Expr::CallExprClass: { const CallExpr *CE = cast<CallExpr>(E); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index cd8b6bb5c2..b8e68d8574 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1222,6 +1222,31 @@ void StmtPrinter::VisitCXXUuidofExpr(CXXUuidofExpr *Node) { OS << ")"; } +void StmtPrinter::VisitUserDefinedLiteral(UserDefinedLiteral *Node) { + switch (Node->getLiteralOperatorKind()) { + case UserDefinedLiteral::LOK_Raw: + OS << cast<StringLiteral>(Node->getArg(0))->getString(); + break; + case UserDefinedLiteral::LOK_Template: { + DeclRefExpr *DRE = cast<DeclRefExpr>(Node->getCallee()); + assert(DRE->hasExplicitTemplateArgs()); + const TemplateArgumentLoc *Args = DRE->getTemplateArgs(); + for (unsigned i = 0, e = DRE->getNumTemplateArgs(); i != e; ++i) { + char C = (char)Args[i].getArgument().getAsIntegral()->getZExtValue(); + OS << C; + } + break; + } + case UserDefinedLiteral::LOK_Integer: + case UserDefinedLiteral::LOK_Floating: + case UserDefinedLiteral::LOK_String: + case UserDefinedLiteral::LOK_Character: + PrintExpr(Node->getCookedLiteral()); + break; + } + OS << Node->getUDSuffix()->getName(); +} + void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { OS << (Node->getValue() ? "true" : "false"); } diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 7935d6d44d..db27f821f5 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -738,6 +738,10 @@ void StmtProfiler::VisitCXXConstCastExpr(const CXXConstCastExpr *S) { VisitCXXNamedCastExpr(S); } +void StmtProfiler::VisitUserDefinedLiteral(const UserDefinedLiteral *S) { + VisitCallExpr(S); +} + void StmtProfiler::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) { VisitExpr(S); ID.AddBoolean(S->getValue()); diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index b06cf44344..f50cc31e9d 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -935,6 +935,7 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { case Stmt::CallExprClass: case Stmt::CXXOperatorCallExprClass: case Stmt::CXXMemberCallExprClass: + case Stmt::UserDefinedLiteralClass: return VisitCallExpr(cast<CallExpr>(S), asc); case Stmt::CaseStmtClass: diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 18aa0fc431..9def5543a8 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -656,6 +656,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { case Expr::CallExprClass: case Expr::CXXMemberCallExprClass: case Expr::CXXOperatorCallExprClass: + case Expr::UserDefinedLiteralClass: return EmitCallExprLValue(cast<CallExpr>(E)); case Expr::VAArgExprClass: return EmitVAArgExprLValue(cast<VAArgExpr>(E)); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6b753a1342..7d99732e68 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1172,10 +1172,27 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { ArrayType::Normal, 0); // Pass &StringTokLocs[0], StringTokLocs.size() to factory! - return Owned(StringLiteral::Create(Context, Literal.GetString(), - Kind, Literal.Pascal, StrTy, - &StringTokLocs[0], - StringTokLocs.size())); + StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(), + Kind, Literal.Pascal, StrTy, + &StringTokLocs[0], + StringTokLocs.size()); + if (Literal.getUDSuffix().empty()) + return Owned(Lit); + + // We're building a user-defined literal. + IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix()); + SourceLocation UDSuffixLoc = StringTokLocs[0]; + // FIXME: = Literal.getUDSuffixLoc(getSourceManager()); + + // C++11 [lex.ext]p5: The literal L is treated as a call of the form + // operator "" X (str, len) + QualType SizeType = Context.getSizeType(); + llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars()); + IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType, + StringTokLocs[0]); + Expr *Args[] = { Lit, LenArg }; + return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc, Args, + StringTokLocs.back()); } ExprResult diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 91e8defcd4..14c773fdb4 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -10895,6 +10895,109 @@ 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(); + + while (F.hasNext()) { + FunctionDecl *D = dyn_cast<FunctionDecl>(F.next()); + // FIXME: using-decls? + + 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; + } + } + } + } + + F.done(); +} + +/// 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; + + // 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( + InitializedEntity::InitializeParameter(Context, FD->getParamDecl(ArgIdx)), + SourceLocation(), Args[ArgIdx]); + if (InputInit.isInvalid()) + return true; + 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); + + if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD)) + return ExprError(); + + if (CheckFunctionCall(FD, UDL)) + return ExprError(); + + return MaybeBindToTemporary(UDL); +} + /// FixOverloadedFunctionReference - E is an expression that refers to /// a C++ overloaded function (possibly with some parentheses and /// perhaps a '&' around it). We have resolved the overloaded function diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 0a0f5c7c32..8d4d934402 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -6088,6 +6088,12 @@ TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) { template<typename Derived> ExprResult +TreeTransform<Derived>::TransformUserDefinedLiteral(UserDefinedLiteral *E) { + return SemaRef.MaybeBindToTemporary(E); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { ExprResult ControllingExpr = getDerived().TransformExpr(E->getControllingExpr()); diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 479805e7e5..a0d7e457e0 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1161,6 +1161,11 @@ void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { E->setRParenLoc(ReadSourceLocation(Record, Idx)); } +void ASTStmtReader::VisitUserDefinedLiteral(UserDefinedLiteral *E) { + VisitCallExpr(E); + E->UDSuffixLoc = ReadSourceLocation(Record, Idx); +} + void ASTStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { VisitExpr(E); E->setValue(Record[Idx++]); @@ -2029,6 +2034,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { /*PathSize*/ Record[ASTStmtReader::NumExprFields]); break; + case EXPR_USER_DEFINED_LITERAL: + S = new (Context) UserDefinedLiteral(Context, Empty); + break; + case EXPR_CXX_BOOL_LITERAL: S = new (Context) CXXBoolLiteralExpr(Empty); break; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 4edfbff288..8b6859cd42 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -720,6 +720,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_CXX_REINTERPRET_CAST); RECORD(EXPR_CXX_CONST_CAST); RECORD(EXPR_CXX_FUNCTIONAL_CAST); + RECORD(EXPR_USER_DEFINED_LITERAL); RECORD(EXPR_CXX_BOOL_LITERAL); RECORD(EXPR_CXX_NULL_PTR_LITERAL); RECORD(EXPR_CXX_TYPEID_EXPR); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 76bbc850c2..a59f2b6a77 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1144,6 +1144,12 @@ void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { Code = serialization::EXPR_CXX_FUNCTIONAL_CAST; } +void ASTStmtWriter::VisitUserDefinedLiteral(UserDefinedLiteral *E) { + VisitCallExpr(E); + Writer.AddSourceLocation(E->UDSuffixLoc, Record); + Code = serialization::EXPR_USER_DEFINED_LITERAL; +} + void ASTStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { VisitExpr(E); Record.push_back(E->getValue()); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 408bcd3528..d19cc9c7d3 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -712,7 +712,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::CallExprClass: case Stmt::CXXOperatorCallExprClass: - case Stmt::CXXMemberCallExprClass: { + case Stmt::CXXMemberCallExprClass: + case Stmt::UserDefinedLiteralClass: { Bldr.takeNodes(Pred); VisitCallExpr(cast<CallExpr>(S), Pred, Dst); Bldr.addNodes(Dst); |