cor3ntin created this revision.
Herald added subscribers: dexonsmith, martong.
cor3ntin requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D99893

Files:
  clang/include/clang/AST/ExprCXX.h
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/include/clang/AST/TextNodeDumper.h
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/Basic/StmtNodes.td
  clang/include/clang/Serialization/ASTBitCodes.h
  clang/lib/AST/Expr.cpp
  clang/lib/AST/ExprCXX.cpp
  clang/lib/AST/ExprClassification.cpp
  clang/lib/AST/ExprConstant.cpp
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/StmtPrinter.cpp
  clang/lib/AST/StmtProfile.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/Sema/SemaExceptionSpec.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/TreeTransform.h
  clang/lib/Serialization/ASTReaderStmt.cpp
  clang/lib/Serialization/ASTWriterStmt.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
  clang/tools/libclang/CXCursor.cpp

Index: clang/tools/libclang/CXCursor.cpp
===================================================================
--- clang/tools/libclang/CXCursor.cpp
+++ clang/tools/libclang/CXCursor.cpp
@@ -480,6 +480,11 @@
     K = CXCursor_CXXStaticCastExpr;
     break;
 
+  case Stmt::CXXStandardLibraryCastExprClass:
+    return MakeCXCursor(
+        cast<CXXStandardLibraryCastExpr>(S)->getOriginalExpression(), Parent,
+        TU, RegionOfInterest);
+
   case Stmt::CXXDynamicCastExprClass:
     K = CXCursor_CXXDynamicCastExpr;
     break;
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1720,6 +1720,7 @@
     case Stmt::ImplicitCastExprClass:
     case Stmt::CStyleCastExprClass:
     case Stmt::CXXStaticCastExprClass:
+    case Stmt::CXXStandardLibraryCastExprClass:
     case Stmt::CXXDynamicCastExprClass:
     case Stmt::CXXReinterpretCastExprClass:
     case Stmt::CXXConstCastExprClass:
Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1652,6 +1652,13 @@
   Code = serialization::EXPR_CXX_STATIC_CAST;
 }
 
+void ASTStmtWriter::VisitCXXStandardLibraryCastExpr(
+    CXXStandardLibraryCastExpr *E) {
+  VisitCastExpr(E);
+  VisitExpr(E);
+  Code = serialization::EXPR_CXX_STATIC_CAST;
+}
+
 void ASTStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
   VisitCXXNamedCastExpr(E);
   Code = serialization::EXPR_CXX_DYNAMIC_CAST;
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1143,6 +1143,12 @@
   E->setIsPartOfExplicitCast(Record.readInt());
 }
 
+void ASTStmtReader::VisitCXXStandardLibraryCastExpr(
+    CXXStandardLibraryCastExpr *E) {
+  VisitCastExpr(E);
+  E->OriginalExpression = Record.readSubExpr();
+}
+
 void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
   VisitCastExpr(E);
   E->setTypeInfoAsWritten(readTypeSourceInfo());
@@ -2930,6 +2936,13 @@
           /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]);
       break;
 
+    case EXPR_CXX_STL_CAST:
+      S = CXXStandardLibraryCastExpr::CreateEmpty(
+          Context,
+          /*PathSize*/ Record[ASTStmtReader::NumExprFields],
+          /*HasFPFeatures*/ Record[ASTStmtReader::NumExprFields + 1]);
+      break;
+
     case EXPR_CSTYLE_CAST:
       S = CStyleCastExpr::CreateEmpty(
           Context,
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -10899,6 +10899,14 @@
   return getDerived().TransformExpr(E->getSubExprAsWritten());
 }
 
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformCXXStandardLibraryCastExpr(
+    CXXStandardLibraryCastExpr *E) {
+  // CXXStandardLibraryCastExpr casts are eliminated during transformation,
+  // since they will be recomputed by semantic analysis after transformation.
+  return E;
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -6443,6 +6443,60 @@
     }
   }
 
+  auto RewriteQualifiedCallsToStandardCastFunction =
+      [&](Expr *Fn) -> ExprResult {
+    auto *ULE = dyn_cast_or_null<OverloadExpr>(Fn->IgnoreParens());
+    if (ArgExprs.size() != 1 || Expr::hasAnyTypeDependentArguments(ArgExprs) ||
+        !ULE || !ULE->getQualifier() ||
+        !ULE->getQualifier()->getAsNamespace()->isStdNamespace())
+      return {};
+
+    ULE->dumpColor();
+    llvm::outs() << "Template Args: " << ULE->getNumTemplateArgs() << "\n";
+
+    IdentifierInfo *ID = ULE->getName().isIdentifier()
+                             ? ULE->getName().getAsIdentifierInfo()
+                             : nullptr;
+    if (!ID)
+      return {};
+
+    Expr *Arg = ArgExprs.front();
+
+    if (ULE->getNumTemplateArgs() == 0 && ID->isStr("move")) {
+      llvm::outs()
+          << "Replacing a call to std::move before overload resolution\n";
+      return CXXStandardLibraryCastExpr::Create(
+          Context, Arg->getType().getNonReferenceType(), VK_XValue, CK_NoOp,
+          Arg, Fn, nullptr, {});
+    }
+
+    if (ULE->getNumTemplateArgs() == 1 && ID->isStr("forward")) {
+      auto TemplateArg = ULE->getTemplateArgs()->getArgument();
+      if (TemplateArg.isDependent() ||
+          TemplateArg.getKind() != TemplateArgument::ArgKind::Type)
+        return {};
+
+      const auto TemplateType = TemplateArg.getAsType().getNonReferenceType();
+      const auto ExpressionType = Arg->getType().getNonReferenceType();
+
+      if (!Context.hasSameType(TemplateType, ExpressionType))
+        return {};
+
+      llvm::outs()
+          << "Replacing a call to std::forward before overload resolution\n";
+      return CXXStandardLibraryCastExpr::Create(Context, TemplateType,
+                                                Arg->getValueKind(), CK_NoOp,
+                                                Arg, Fn, nullptr, {});
+    }
+
+    return {};
+  };
+
+  ExprResult E = RewriteQualifiedCallsToStandardCastFunction(Fn);
+  if (E.isUsable()) {
+    return E;
+  }
+
   // Check for overloaded calls.  This can happen even in C due to extensions.
   if (Fn->getType() == Context.OverloadTy) {
     OverloadExpr::FindResult find = OverloadExpr::find(Fn);
@@ -6846,7 +6900,29 @@
       return ExprError();
   }
 
-  return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), FDecl);
+  auto TransformStdMoveAndForwardIntoCast = [&](CallExpr *Call) -> Expr * {
+    const bool isStd = NDecl && NDecl->isInStdNamespace();
+    if (!getLangOpts().CPlusPlus || !isStd || !NDecl)
+      return Call;
+
+    if (Call->getNumArgs() != 1 && !(NDecl->getName().compare("move") == 0 ||
+                                     NDecl->getName().compare("forward") == 0))
+      return Call;
+
+    Expr *A = TheCall->getArg(0);
+    if (A->getType().getCanonicalType().getNonReferenceType() !=
+        TheCall->getType().getCanonicalType().getNonReferenceType())
+      return Call;
+
+    if (A->isRValue() && Context.hasSameType(A->getType(), TheCall->getType()))
+      return A;
+
+    return CXXStandardLibraryCastExpr::Create(
+        Context, TheCall->getType(), TheCall->getValueKind(), CastKind::CK_NoOp,
+        A, TheCall, nullptr, {});
+  };
+  return CheckForImmediateInvocation(
+      MaybeBindToTemporary(TransformStdMoveAndForwardIntoCast(TheCall)), FDecl);
 }
 
 ExprResult
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===================================================================
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1305,6 +1305,7 @@
   case Expr::CompoundAssignOperatorClass:
   case Expr::CStyleCastExprClass:
   case Expr::CXXStaticCastExprClass:
+  case Expr::CXXStandardLibraryCastExprClass:
   case Expr::CXXFunctionalCastExprClass:
   case Expr::ImplicitCastExprClass:
   case Expr::MaterializeTemporaryExprClass:
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1413,6 +1413,7 @@
   case Expr::CStyleCastExprClass:
   case Expr::CXXFunctionalCastExprClass:
   case Expr::CXXStaticCastExprClass:
+  case Expr::CXXStandardLibraryCastExprClass:
   case Expr::CXXDynamicCastExprClass:
   case Expr::CXXReinterpretCastExprClass:
   case Expr::CXXConstCastExprClass:
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -201,6 +201,7 @@
   REGISTER_MATCHER(cxxReinterpretCastExpr);
   REGISTER_MATCHER(cxxRewrittenBinaryOperator);
   REGISTER_MATCHER(cxxStaticCastExpr);
+  REGISTER_MATCHER(cxxStandardLibraryCastExpr);
   REGISTER_MATCHER(cxxStdInitializerListExpr);
   REGISTER_MATCHER(cxxTemporaryObjectExpr);
   REGISTER_MATCHER(cxxThisExpr);
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -956,6 +956,8 @@
     explicitCastExpr;
 const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr>
     implicitCastExpr;
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStandardLibraryCastExpr>
+    cssStandardLibraryCastExpr;
 const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
 const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr>
     cxxFunctionalCastExpr;
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1146,6 +1146,17 @@
     printFPOptions(Node->getFPFeatures());
 }
 
+void TextNodeDumper::VisitCXXStandardLibraryCast(
+    const CXXStandardLibraryCastExpr *Node) {
+  VisitCastExpr(Node);
+  OS << "<" << Node->getType().getAsString() << ">"
+     << "<" << Node->getCastKindName();
+  dumpBasePath(OS, Node);
+  OS << ">";
+
+  // Visit(Node->getOriginalExpression());
+}
+
 void TextNodeDumper::VisitCXXUnresolvedConstructExpr(
     const CXXUnresolvedConstructExpr *Node) {
   dumpType(Node->getTypeAsWritten());
Index: clang/lib/AST/StmtProfile.cpp
===================================================================
--- clang/lib/AST/StmtProfile.cpp
+++ clang/lib/AST/StmtProfile.cpp
@@ -1305,6 +1305,11 @@
   ID.AddInteger(S->getValueKind());
 }
 
+void StmtProfiler::VisitCXXStandardLibraryCastExpr(
+    const CXXStandardLibraryCastExpr *S) {
+  VisitCastExpr(S);
+}
+
 void StmtProfiler::VisitExplicitCastExpr(const ExplicitCastExpr *S) {
   VisitCastExpr(S);
   VisitType(S->getTypeAsWritten());
Index: clang/lib/AST/StmtPrinter.cpp
===================================================================
--- clang/lib/AST/StmtPrinter.cpp
+++ clang/lib/AST/StmtPrinter.cpp
@@ -1495,6 +1495,12 @@
   PrintExpr(Node->getSubExpr());
 }
 
+void StmtPrinter::VisitCXXStandardLibraryCastExpr(
+    CXXStandardLibraryCastExpr *Node) {
+  // No need to print anything, simply forward to the subexpression.
+  PrintExpr(Node->getSubExpr());
+}
+
 void StmtPrinter::VisitBinaryOperator(BinaryOperator *Node) {
   PrintExpr(Node->getLHS());
   OS << " " << BinaryOperator::getOpcodeStr(Node->getOpcode()) << " ";
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -4661,6 +4661,7 @@
     break;
   }
 
+  case Expr::CXXStandardLibraryCastExprClass:
   case Expr::CXXStaticCastExprClass:
     NotPrimaryExpr();
     mangleCastExpression(E, "sc");
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -15362,6 +15362,7 @@
   case Expr::CXXFunctionalCastExprClass:
   case Expr::CXXStaticCastExprClass:
   case Expr::CXXReinterpretCastExprClass:
+  case Expr::CXXStandardLibraryCastExprClass:
   case Expr::CXXConstCastExprClass:
   case Expr::ObjCBridgedCastExprClass: {
     const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
Index: clang/lib/AST/ExprClassification.cpp
===================================================================
--- clang/lib/AST/ExprClassification.cpp
+++ clang/lib/AST/ExprClassification.cpp
@@ -363,6 +363,9 @@
     if (!Lang.CPlusPlus) return Cl::CL_PRValue;
     return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten());
 
+  case Expr::CXXStandardLibraryCastExprClass:
+    return ClassifyExprValueKind(Lang, E, E->getValueKind());
+
   case Expr::CXXUnresolvedConstructExprClass:
     return ClassifyUnnamed(Ctx,
                       cast<CXXUnresolvedConstructExpr>(E)->getTypeAsWritten());
Index: clang/lib/AST/ExprCXX.cpp
===================================================================
--- clang/lib/AST/ExprCXX.cpp
+++ clang/lib/AST/ExprCXX.cpp
@@ -871,6 +871,40 @@
   return RParenLoc.isValid() ? RParenLoc : getSubExpr()->getEndLoc();
 }
 
+CXXStandardLibraryCastExpr *CXXStandardLibraryCastExpr::Create(
+    const ASTContext &C, QualType T, ExprValueKind VK, CastKind Kind, Expr *Op,
+    Expr *OriginalExpression, const CXXCastPath *BasePath,
+    FPOptionsOverride FPO) {
+  unsigned PathSize = (BasePath ? BasePath->size() : 0);
+  void *Buffer =
+      C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+          PathSize, FPO.requiresTrailingStorage()));
+  auto *E = new (Buffer) CXXStandardLibraryCastExpr(
+      T, VK, Kind, Op, OriginalExpression, PathSize, BasePath, FPO);
+  if (PathSize)
+    std::uninitialized_copy_n(BasePath->data(), BasePath->size(),
+                              E->getTrailingObjects<CXXBaseSpecifier *>());
+  return E;
+}
+
+CXXStandardLibraryCastExpr *
+CXXStandardLibraryCastExpr::CreateEmpty(const ASTContext &C, unsigned PathSize,
+                                        bool HasFPFeatures) {
+  void *Buffer =
+      C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *, FPOptionsOverride>(
+          PathSize, HasFPFeatures));
+  return new (Buffer)
+      CXXStandardLibraryCastExpr(EmptyShell(), PathSize, HasFPFeatures);
+}
+
+SourceLocation CXXStandardLibraryCastExpr::getBeginLoc() const {
+  return OriginalExpression->getBeginLoc();
+}
+
+SourceLocation CXXStandardLibraryCastExpr::getEndLoc() const {
+  return OriginalExpression->getEndLoc();
+}
+
 UserDefinedLiteral::UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args,
                                        QualType Ty, ExprValueKind VK,
                                        SourceLocation LitEndLoc,
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -3432,6 +3432,7 @@
   case CXXStaticCastExprClass:
   case CXXReinterpretCastExprClass:
   case CXXConstCastExprClass:
+  case CXXStandardLibraryCastExprClass:
   case CXXAddrspaceCastExprClass:
   case CXXFunctionalCastExprClass:
   case BuiltinBitCastExprClass: {
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang/include/clang/Serialization/ASTBitCodes.h
+++ clang/include/clang/Serialization/ASTBitCodes.h
@@ -1800,6 +1800,9 @@
   /// A CXXStaticCastExpr record.
   EXPR_CXX_STATIC_CAST,
 
+  /// A CXXStandardLibraryCastExpr record.
+  EXPR_CXX_STL_CAST,
+
   /// A CXXDynamicCastExpr record.
   EXPR_CXX_DYNAMIC_CAST,
 
Index: clang/include/clang/Basic/StmtNodes.td
===================================================================
--- clang/include/clang/Basic/StmtNodes.td
+++ clang/include/clang/Basic/StmtNodes.td
@@ -123,6 +123,7 @@
 def CXXConstCastExpr : StmtNode<CXXNamedCastExpr>;
 def CXXAddrspaceCastExpr : StmtNode<CXXNamedCastExpr>;
 def CXXFunctionalCastExpr : StmtNode<ExplicitCastExpr>;
+def CXXStandardLibraryCastExpr : StmtNode<CastExpr>;
 def CXXTypeidExpr : StmtNode<Expr>;
 def UserDefinedLiteral : StmtNode<CallExpr>;
 def CXXBoolLiteralExpr : StmtNode<Expr>;
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2574,6 +2574,10 @@
 extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr>
     cStyleCastExpr;
 
+extern const internal::VariadicDynCastAllOfMatcher<Stmt,
+                                                   CXXStandardLibraryCastExpr>
+    cxxStandardLibraryCastExpr;
+
 /// Matches explicit cast expressions.
 ///
 /// Matches any cast expression written in user code, whether it be a
Index: clang/include/clang/AST/TextNodeDumper.h
===================================================================
--- clang/include/clang/AST/TextNodeDumper.h
+++ clang/include/clang/AST/TextNodeDumper.h
@@ -271,6 +271,7 @@
   void VisitCXXThisExpr(const CXXThisExpr *Node);
   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *Node);
+  void VisitCXXStandardLibraryCast(const CXXStandardLibraryCastExpr *Node);
   void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node);
   void VisitCXXConstructExpr(const CXXConstructExpr *Node);
   void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2312,6 +2312,8 @@
      // source code.
     })
 
+DEF_TRAVERSE_STMT(CXXStandardLibraryCastExpr, {})
+
 DEF_TRAVERSE_STMT(CStyleCastExpr, {
   TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
 })
Index: clang/include/clang/AST/ExprCXX.h
===================================================================
--- clang/include/clang/AST/ExprCXX.h
+++ clang/include/clang/AST/ExprCXX.h
@@ -1779,6 +1779,55 @@
   }
 };
 
+class CXXStandardLibraryCastExpr final
+    : public CastExpr,
+      private llvm::TrailingObjects<CXXStandardLibraryCastExpr,
+                                    CXXBaseSpecifier *, FPOptionsOverride> {
+  friend class ASTStmtReader;
+
+  CXXStandardLibraryCastExpr(QualType exprTy, ExprValueKind VK, CastKind kind,
+                             Expr *op, Expr *OriginalExpression,
+                             unsigned PathSize, const CXXCastPath *BasePath,
+                             FPOptionsOverride FPO)
+      : CastExpr(CXXStandardLibraryCastExprClass, exprTy, VK, kind, op,
+                 PathSize, FPO.requiresTrailingStorage()),
+        OriginalExpression(OriginalExpression) {}
+
+  explicit CXXStandardLibraryCastExpr(EmptyShell Shell, unsigned PathSize,
+                                      bool HasFPFeatures)
+      : CastExpr(CXXStandardLibraryCastExprClass, Shell, PathSize,
+                 HasFPFeatures) {}
+
+  unsigned numTrailingObjects(OverloadToken<CXXBaseSpecifier *>) const {
+    return path_size();
+  }
+
+  Expr *OriginalExpression;
+
+public:
+  friend TrailingObjects;
+  friend class CastExpr;
+
+  static CXXStandardLibraryCastExpr *
+  Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind,
+         Expr *Op, Expr *OriginalExpression, const CXXCastPath *BasePath,
+         FPOptionsOverride FPO);
+
+  static CXXStandardLibraryCastExpr *
+  CreateEmpty(const ASTContext &Context, unsigned PathSize, bool HasFPFeatures);
+
+  /* Expr* getOriginalExpression() const {
+       return OriginalExpression;
+   }*/
+
+  SourceLocation getBeginLoc() const LLVM_READONLY;
+  SourceLocation getEndLoc() const LLVM_READONLY;
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == CXXStandardLibraryCastExprClass;
+  }
+};
+
 /// Represents a C++ functional cast expression that builds a
 /// temporary object.
 ///
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to