diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-07 08:35:16 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-07 08:35:16 +0000 |
commit | c67fdd4eb95f1eed299af302e407bbdb916bdfaf (patch) | |
tree | fc8792466a8ac8c7c095b48ec7d3582009050b7a /clang/lib/AST | |
parent | 1a1b54a2da5d17c2e03a5b8fec8a85968fa35147 (diff) | |
download | bcm5719-llvm-c67fdd4eb95f1eed299af302e407bbdb916bdfaf.tar.gz bcm5719-llvm-c67fdd4eb95f1eed299af302e407bbdb916bdfaf.zip |
AST representation for user-defined literals, plus just enough of semantic
analysis to make the AST representation testable. They are represented by a
new UserDefinedLiteral AST node, which is a sugared CallExpr. All semantic
properties, including full CodeGen support, are achieved for free by this
representation.
UserDefinedLiterals can never be dependent, so no custom instantiation
behavior is required. They are mangled as if they were direct calls to the
underlying literal operator. This matches g++'s apparent behavior (but not its
actual mangling, which is broken for literal-operator-ids).
User-defined *string* literals are now fully-operational, but the semantic
analysis is quite hacky and needs more work. No other forms of user-defined
literal are created yet, but the AST support for them is present.
This patch committed after midnight because we had already hit the quota for
new kinds of literal yesterday.
llvm-svn: 152211
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 6 | ||||
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 33 | ||||
-rw-r--r-- | clang/lib/AST/ExprClassification.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 3 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 25 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 4 |
7 files changed, 71 insertions, 2 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index e35091a1017..0fdca5a33b1 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/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/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index dc559f0940f..039d70cfc56 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/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/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 693e28c8a45..00160a00737 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/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/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 08794f355f7..947f661c2ca 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/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/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index ea6e8b2e23c..c4eed7c34d6 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/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/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index cd8b6bb5c23..b8e68d8574a 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/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/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 7935d6d44d1..db27f821f5b 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/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()); |