diff options
Diffstat (limited to 'clang/lib')
| -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 | ||||
| -rw-r--r-- | clang/lib/Analysis/CFG.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 25 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 103 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 6 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 3 | 
16 files changed, 221 insertions, 7 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()); diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index b06cf443442..f50cc31e9d8 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/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/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 18aa0fc4317..9def5543a84 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6b753a13421..7d99732e682 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 91e8defcd45..14c773fdb4f 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0a0f5c7c328..8d4d934402b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/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/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 479805e7e53..a0d7e457e0c 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/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/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 4edfbff2888..8b6859cd427 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/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/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 76bbc850c21..a59f2b6a778 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/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/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 408bcd35286..d19cc9c7d3d 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/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);  | 

