aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ExprConstant.cpp3
-rw-r--r--lib/AST/StmtPrinter.cpp5
-rw-r--r--lib/AST/StmtProfile.cpp6
-rw-r--r--lib/Checker/GRExprEngine.cpp1
-rw-r--r--lib/CodeGen/Mangle.cpp1
-rw-r--r--lib/Lex/Lexer.cpp31
-rw-r--r--lib/Lex/LiteralSupport.cpp28
-rw-r--r--lib/Lex/Preprocessor.cpp26
-rw-r--r--lib/Parse/ParseExpr.cpp3
-rw-r--r--lib/Parse/ParseStmt.cpp3
-rw-r--r--lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--lib/Sema/SemaExpr.cpp19
-rw-r--r--lib/Sema/SemaExprCXX.cpp58
-rw-r--r--lib/Sema/TreeTransform.h6
14 files changed, 164 insertions, 29 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 14cbbaf0e8..d067668f4b 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -2423,7 +2423,8 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::UnaryTypeTraitExprClass:
return NoDiag();
case Expr::CallExprClass:
- case Expr::CXXOperatorCallExprClass: {
+ case Expr::CXXOperatorCallExprClass:
+ case Expr::UDLiteralExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
if (CE->isBuiltinCall(Ctx))
return CheckEvalInICE(E, Ctx);
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index ea528c2dae..084bdb3ed6 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1199,6 +1199,11 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
}
}
+void StmtPrinter::VisitUDLiteralExpr(UDLiteralExpr *Node) {
+ VisitStmt(Node->getBaseLiteral());
+ OS << Node->getUDSuffix()->getName();
+}
+
static const char *getTypeTraitName(UnaryTypeTrait UTT) {
switch (UTT) {
default: assert(false && "Unknown type trait");
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 098aec0a19..79454748dd 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -828,6 +828,12 @@ void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) {
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
+void StmtProfiler::VisitUDLiteralExpr(UDLiteralExpr *S) {
+ VisitExpr(S);
+ VisitStmt(S->getBaseLiteral());
+ ID.AddString(S->getUDSuffix()->getName());
+}
+
void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) {
VisitExpr(S);
}
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index c9173aa92a..059749d16f 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -886,6 +886,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
}
case Stmt::CallExprClass:
+ case Stmt::UDLiteralExprClass:
case Stmt::CXXOperatorCallExprClass: {
const CallExpr* C = cast<CallExpr>(S);
VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index c06b4fc699..51b07a1327 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -1634,6 +1634,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
break;
case Expr::CXXMemberCallExprClass: // fallthrough
+ case Expr::UDLiteralExprClass:
case Expr::CallExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
Out << "cl";
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 6cd1873e28..b4cafb49f8 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -548,6 +548,11 @@ static void InitCharacterInfo() {
isInited = true;
}
+/// isIdentifierStart - Return true if this is the start character of an
+/// identifier, which is [a-zA-Z_].
+static inline bool isIdentifierStart(unsigned char c) {
+ return (CharInfo[c] & (CHAR_LETTER|CHAR_UNDER)) ? true : false;
+}
/// isIdentifierBody - Return true if this is the body character of an
/// identifier, which is [a-zA-Z0-9_].
@@ -982,8 +987,30 @@ void Lexer::LexStringLiteral(Token &Result, const char *CurPtr, bool Wide) {
// Update the location of the token as well as the BufferPtr instance var.
const char *TokStart = BufferPtr;
- FormTokenWithChars(Result, CurPtr,
- Wide ? tok::wide_string_literal : tok::string_literal);
+ tok::TokenKind Kind = Wide ? tok::wide_string_literal : tok::string_literal;
+
+ // FIXME: Handle UCNs
+ unsigned Size;
+ if (PP && PP->getLangOptions().CPlusPlus0x &&
+ isIdentifierStart(getCharAndSize(CurPtr, Size))) {
+ Result.makeUserDefinedLiteral(ExtraDataAllocator);
+ Result.setFlagValue(Token::LiteralPortionClean, !Result.needsCleaning());
+ Result.setKind(Kind);
+ Result.setLiteralLength(CurPtr - BufferPtr);
+
+ // FIXME: We hack around the lexer's routines a lot here.
+ BufferPtr = CurPtr;
+ bool OldRawMode = LexingRawMode;
+ LexingRawMode = true;
+ LexIdentifier(Result, ConsumeChar(CurPtr, Size, Result));
+ LexingRawMode = OldRawMode;
+ PP->LookUpIdentifierInfo(Result, CurPtr);
+
+ CurPtr = BufferPtr;
+ BufferPtr = TokStart;
+ }
+
+ FormTokenWithChars(Result, CurPtr, Kind);
Result.setLiteralData(TokStart);
}
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index a12c4ae0d4..eb7337a565 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -758,30 +758,38 @@ CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
///
StringLiteralParser::
StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
- Preprocessor &pp, bool Complain) : PP(pp) {
+ Preprocessor &pp, bool Complain) : PP(pp), hadError(false) {
// Scan all of the string portions, remember the max individual token length,
// computing a bound on the concatenated string length, and see whether any
// piece is a wide-string. If any of the string portions is a wide-string
// literal, the result is a wide-string literal [C99 6.4.5p4].
- MaxTokenLength = StringToks[0].getLength();
- SizeBound = StringToks[0].getLength()-2; // -2 for "".
+ MaxTokenLength = StringToks[0].getLiteralLength();
+ SizeBound = StringToks[0].getLiteralLength()-2; // -2 for "".
AnyWide = StringToks[0].is(tok::wide_string_literal);
-
- hadError = false;
+ UDSuffix = StringToks[0].getIdentifierInfo();
// Implement Translation Phase #6: concatenation of string literals
/// (C99 5.1.1.2p1). The common case is only one string fragment.
for (unsigned i = 1; i != NumStringToks; ++i) {
// The string could be shorter than this if it needs cleaning, but this is a
// reasonable bound, which is all we need.
- SizeBound += StringToks[i].getLength()-2; // -2 for "".
+ SizeBound += StringToks[i].getLiteralLength()-2; // -2 for "".
// Remember maximum string piece length.
- if (StringToks[i].getLength() > MaxTokenLength)
- MaxTokenLength = StringToks[i].getLength();
+ if (StringToks[i].getLiteralLength() > MaxTokenLength)
+ MaxTokenLength = StringToks[i].getLiteralLength();
// Remember if we see any wide strings.
AnyWide |= StringToks[i].is(tok::wide_string_literal);
+
+ if (StringToks[i].isUserDefinedLiteral()) {
+ if (UDSuffix && UDSuffix != StringToks[i].getIdentifierInfo()) {
+ // FIXME: Improve location and note previous
+ PP.Diag(StringToks[0].getLocation(), diag::err_ud_suffix_mismatch);
+ hadError = true;
+ } else if (!UDSuffix)
+ UDSuffix = StringToks[0].getIdentifierInfo();
+ }
}
// Include space for the null terminator.
@@ -823,7 +831,7 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
// and 'spelled' tokens can only shrink.
bool StringInvalid = false;
unsigned ThisTokLen = PP.getSpelling(StringToks[i], ThisTokBuf,
- &StringInvalid);
+ &StringInvalid, true);
if (StringInvalid) {
hadError = 1;
continue;
@@ -938,7 +946,7 @@ unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok,
bool Complain) {
// Get the spelling of the token.
llvm::SmallString<16> SpellingBuffer;
- SpellingBuffer.resize(Tok.getLength());
+ SpellingBuffer.resize(Tok.getLiteralLength());
bool StringInvalid = false;
const char *SpellingPtr = &SpellingBuffer[0];
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 5160acf19e..f52d35494a 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -352,15 +352,25 @@ std::string Preprocessor::getSpelling(const Token &Tok, bool *Invalid) const {
/// to point to a constant buffer with the data already in it (avoiding a
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
-unsigned Preprocessor::getSpelling(const Token &Tok,
- const char *&Buffer, bool *Invalid) const {
+///
+/// If LiteralOnly is specified, only the literal portion of the token is
+/// processed.
+unsigned Preprocessor::getSpelling(const Token &Tok, const char *&Buffer,
+ bool *Invalid, bool LiteralOnly) const {
assert((int)Tok.getLength() >= 0 && "Token character range is bogus!");
+ assert((!LiteralOnly || Tok.isLiteral()) &&
+ "LiteralOnly used on a non-literal token");
+
+ unsigned (Token::*getLength) () const =
+ LiteralOnly ? &Token::getLiteralLength : &Token::getLength;
// If this token is an identifier, just return the string from the identifier
// table, which is very quick.
if (const IdentifierInfo *II = Tok.getIdentifierInfo()) {
- Buffer = II->getNameStart();
- return II->getLength();
+ if (!Tok.isUserDefinedLiteral()) {
+ Buffer = II->getNameStart();
+ return II->getLength();
+ }
}
// Otherwise, compute the start of the token in the input lexer buffer.
@@ -381,20 +391,20 @@ unsigned Preprocessor::getSpelling(const Token &Tok,
}
// If this token contains nothing interesting, return it directly.
- if (!Tok.needsCleaning()) {
+ if (!(LiteralOnly ? Tok.literalNeedsCleaning() : Tok.needsCleaning())) {
Buffer = TokStart;
- return Tok.getLength();
+ return (Tok.*getLength)();
}
// Otherwise, hard case, relex the characters into the string.
char *OutBuf = const_cast<char*>(Buffer);
- for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength();
+ for (const char *Ptr = TokStart, *End = TokStart+(Tok.*getLength)();
Ptr != End; ) {
unsigned CharSize;
*OutBuf++ = Lexer::getCharAndSizeNoWarn(Ptr, CharSize, Features);
Ptr += CharSize;
}
- assert(unsigned(OutBuf-Buffer) != Tok.getLength() &&
+ assert(unsigned(OutBuf-Buffer) != (Tok.*getLength)() &&
"NeedsCleaning flag set on something that didn't need cleaning!");
return OutBuf-Buffer;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 290b72c4c0..2ade77a907 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1568,7 +1568,8 @@ ExprResult Parser::ParseStringLiteralExpression() {
} while (isTokenStringLiteral());
// Pass the set of string tokens, ready for concatenation, to the actions.
- return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size());
+ return Actions.ActOnStringLiteral(getCurScope(), &StringToks[0],
+ StringToks.size());
}
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index af927285a4..94b8c3baac 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -1244,11 +1244,12 @@ StmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
Tok.isNot(tok::eof));
}
Token t;
+ t.startToken();
t.setKind(tok::string_literal);
t.setLiteralData("\"/*FIXME: not done*/\"");
t.clearFlag(Token::NeedsCleaning);
t.setLength(21);
- ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
+ ExprResult AsmString(Actions.ActOnStringLiteral(getCurScope(), &t, 1));
ExprVector Constraints(Actions);
ExprVector Exprs(Actions);
ExprVector Clobbers(Actions);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 35920c2792..4abeaaf246 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5932,6 +5932,9 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
return true;
}
+ if (FnDecl->getDeclName().getCXXLiteralIdentifier()->getName()[0] != '_')
+ Diag(FnDecl->getLocation(), diag::warn_literal_operator_no_underscore);
+
bool Valid = false;
// template <char...> type operator "" name() is the only valid template
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 1a065eb63c..4d0ac90d39 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -375,7 +375,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
/// string.
///
ExprResult
-Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
+Sema::ActOnStringLiteral(Scope *S, const Token *StringToks,
+ unsigned NumStringToks) {
assert(NumStringToks && "Must have at least one string!");
StringLiteralParser Literal(StringToks, NumStringToks, PP);
@@ -401,12 +402,18 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
llvm::APInt(32, Literal.GetNumStringChars()+1),
ArrayType::Normal, 0);
+ StringLiteral *SL = StringLiteral::Create(Context, Literal.GetString(),
+ Literal.GetStringLength(),
+ Literal.AnyWide, StrTy,
+ &StringTokLocs[0],
+ StringTokLocs.size());
+
+ if (Literal.isUserDefinedLiteral())
+ return BuildUDStringLiteralExpr(S, SL, Literal.GetNumStringChars(),
+ Literal.getUDSuffix());
+
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
- return Owned(StringLiteral::Create(Context, Literal.GetString(),
- Literal.GetStringLength(),
- Literal.AnyWide, StrTy,
- &StringTokLocs[0],
- StringTokLocs.size()));
+ return Owned(SL);
}
/// ShouldSnapshotBlockValueReference - Return true if a reference inside of
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 5720d931b6..344196cc6f 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -3057,3 +3057,61 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) {
if (!FullExpr) return ExprError();
return MaybeCreateCXXExprWithTemporaries(FullExpr);
}
+
+ExprResult Sema::BuildUDStringLiteralExpr(Scope *S, StringLiteral *SL,
+ unsigned L, IdentifierInfo *II) {
+ DeclarationName DN = Context.DeclarationNames.getCXXLiteralOperatorName(II);
+
+ LookupResult R(*this, DN, SL->getLocStart(), LookupOrdinaryName);
+ LookupName(R, S);
+
+ llvm::APInt APL(Context.getTypeSize(Context.getSizeType()), L);
+
+ Expr *Args[2];
+ Args[0] = SL;
+ Args[1] = new (Context) IntegerLiteral(Context, APL, Context.getSizeType(),
+ SourceLocation());
+
+ OverloadCandidateSet CandidateSet(SL->getLocStart());
+ AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, CandidateSet);
+ OverloadCandidateSet::iterator Best;
+ switch (CandidateSet.BestViableFunction(*this, SL->getLocStart(), Best)) {
+ case OR_Ambiguous:
+ llvm_unreachable("UD literals should not have ambiguous overloads");
+ return ExprError();
+ case OR_No_Viable_Function:
+ Diag(SL->getLocStart(), diag::err_literal_operator_overload)
+ << SL->getSourceRange() << II->getName();
+ return ExprError();
+ case OR_Deleted:
+ Diag(SL->getLocStart(), diag::err_literal_operator_deleted)
+ << SL->getSourceRange() << II->getName();
+ //FIXME: Note the deleted function
+ return ExprError();
+ case OR_Success:
+ break;
+ }
+
+ assert(Best->Function && "Literal operator function not a real function");
+ FunctionDecl *FD = Best->Function;
+
+ ExprResult InputInit
+ = PerformCopyInitialization(InitializedEntity::InitializeParameter(
+ FD->getParamDecl(0)),
+ SourceLocation(), Owned(SL));
+ if (InputInit.isInvalid())
+ return ExprError();
+ Args[0] = InputInit.takeAs<Expr>();
+
+ QualType ResultTy = FD->getResultType().getNonReferenceType();
+ Expr *Fn = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
+ UsualUnaryConversions(Fn);
+
+ UDLiteralExpr *E = new (Context) UDLiteralExpr(Context, SL, Fn, Args, 2,
+ ResultTy);
+
+ if (CheckCallReturnType(FD->getResultType(), SL->getLocStart(), E, FD))
+ return ExprError();
+
+ return MaybeBindToTemporary(E);
+}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 08cfd68d66..8784c844be 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -6030,6 +6030,12 @@ TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformUDLiteralExpr(UDLiteralExpr *E) {
+ return SemaRef.Owned(E->Retain());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
// Transform arguments.
bool ArgChanged = false;