diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 3 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 6 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 1 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 31 | ||||
-rw-r--r-- | lib/Lex/LiteralSupport.cpp | 28 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 26 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 58 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 6 |
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; |