]> granicus.if.org Git - clang/commitdiff
Introduce a new expression type, CXXUnresolvedConstructExpr, to
authorDouglas Gregor <dgregor@apple.com>
Wed, 20 May 2009 18:46:25 +0000 (18:46 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 20 May 2009 18:46:25 +0000 (18:46 +0000)
describe the construction of a value of a given type using function
syntax, e.g.,

  T(a1, a2, ..., aN)

when the type or any of its arguments are type-dependent. In this
case, we don't know what kind of type-construction this will be: it
might construct a temporary of type 'T' (which might be a class or
non-class type) or might perform a conversion to type 'T'. Also,
implement printing of and template instantiation for this new
expression type. Due to the change in Sema::ActOnCXXTypeConstructExpr,
our existing tests cover template instantiation of this new expression
node.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72176 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ExprCXX.h
include/clang/AST/StmtNodes.def
lib/AST/ExprCXX.cpp
lib/AST/StmtPrinter.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaTemplateInstantiateExpr.cpp

index dd6a26e3d3d1db9c479630d422e1cfb2cf8bf0d3..f3c82441603c01128d79054afeec050aecaa09a7 100644 (file)
@@ -982,6 +982,103 @@ public:
   virtual child_iterator child_end();
 };
 
+/// \brief Describes an explicit type conversion that uses functional
+/// notion but could not be resolved because one or more arguments are
+/// type-dependent.
+///
+/// The explicit type conversions expressed by
+/// CXXUnresolvedConstructExpr have the form \c T(a1, a2, ..., aN),
+/// where \c T is some type and \c a1, a2, ..., aN are values, and
+/// either \C T is a dependent type or one or more of the \c a's is
+/// type-dependent. For example, this would occur in a template such
+/// as:
+///
+/// \code
+///   template<typename T, typename A1>
+///   inline T make_a(const A1& a1) {
+///     return T(a1);
+///   }
+/// \endcode
+///
+/// When the returned expression is instantiated, it may resolve to a
+/// constructor call, conversion function call, or some kind of type
+/// conversion.
+class CXXUnresolvedConstructExpr : public Expr {
+  /// \brief The starting location of the type
+  SourceLocation TyBeginLoc;
+
+  /// \brief The type being constructed.
+  QualType Type;
+
+  /// \brief The location of the left parentheses ('(').
+  SourceLocation LParenLoc;
+
+  /// \brief The location of the right parentheses (')').
+  SourceLocation RParenLoc;
+
+  /// \brief The number of arguments used to construct the type.
+  unsigned NumArgs;
+  
+  CXXUnresolvedConstructExpr(SourceLocation TyBegin,
+                             QualType T,
+                             SourceLocation LParenLoc,
+                             Expr **Args,
+                             unsigned NumArgs,
+                             SourceLocation RParenLoc);
+
+public:
+  static CXXUnresolvedConstructExpr *Create(ASTContext &C, 
+                                            SourceLocation TyBegin,
+                                            QualType T,
+                                            SourceLocation LParenLoc,
+                                            Expr **Args,
+                                            unsigned NumArgs,
+                                            SourceLocation RParenLoc);
+
+  /// \brief Retrieve the source location where the type begins.
+  SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
+  void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
+
+  /// \brief Retrieve the type that is being constructed, as specified
+  /// in the source code.
+  QualType getTypeAsWritten() const { return Type; }
+  void setTypeAsWritten(QualType T) { Type = T; }
+
+  /// \brief Retrieve the location of the left parentheses ('(') that
+  /// precedes the argument list.
+  SourceLocation getLParenLoc() const { return LParenLoc; }
+  void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+
+  /// \brief Retrieve the location of the right parentheses (')') that
+  /// follows the argument list.
+  SourceLocation getRParenLoc() const { return RParenLoc; }
+  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+  /// \brief Retrieve the number of arguments.
+  unsigned arg_size() const { return NumArgs; }
+
+  typedef Expr** arg_iterator;
+  arg_iterator arg_begin() { return reinterpret_cast<Expr**>(this + 1); }
+  arg_iterator arg_end() { return arg_begin() + NumArgs; }
+
+  Expr *getArg(unsigned I) {
+    assert(I < NumArgs && "Argument index out-of-range");
+    return *(arg_begin() + I);
+  }
+
+  virtual SourceRange getSourceRange() const {
+    return SourceRange(TyBeginLoc, RParenLoc);
+  }
+  static bool classof(const Stmt *T) { 
+    return T->getStmtClass() == CXXUnresolvedConstructExprClass;
+  }
+  static bool classof(const CXXUnresolvedConstructExpr *) { return true; }
+
+  // Iterators
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+};
+
 }  // end namespace clang
 
 #endif
index 03203f2fa80487c4aeab9b5d01d99b765497683c..98e65d5cf9e178ee24be87896f4d4425f194e1ec 100644 (file)
@@ -126,6 +126,7 @@ EXPR(UnresolvedDeclRefExpr  , Expr)
 EXPR(CXXConstructExpr       , Expr)
 EXPR(CXXExprWithTemporaries , Expr)
 EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
+EXPR(CXXUnresolvedConstructExpr, Expr)
 
 // Obj-C Expressions.
 EXPR(ObjCStringLiteral    , Expr)
index a138f01c778ce8e7ef1c2ab41c7352f537869587..a73843ca363cad78b012a0fd1c3471fca029738a 100644 (file)
@@ -314,6 +314,45 @@ Stmt::child_iterator CXXExprWithTemporaries::child_end() {
   return &SubExpr + 1;
 }
 
+CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(
+                                                 SourceLocation TyBeginLoc,
+                                                 QualType T,
+                                                 SourceLocation LParenLoc,
+                                                 Expr **Args,
+                                                 unsigned NumArgs,
+                                                 SourceLocation RParenLoc)
+  : Expr(CXXUnresolvedConstructExprClass, T.getNonReferenceType(),
+         T->isDependentType(), true),
+    TyBeginLoc(TyBeginLoc),
+    Type(T),
+    LParenLoc(LParenLoc),
+    RParenLoc(RParenLoc),
+    NumArgs(NumArgs) {
+  Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1);
+  memcpy(StoredArgs, Args, sizeof(Expr *) * NumArgs);
+}
+
+CXXUnresolvedConstructExpr *
+CXXUnresolvedConstructExpr::Create(ASTContext &C, 
+                                   SourceLocation TyBegin,
+                                   QualType T,
+                                   SourceLocation LParenLoc,
+                                   Expr **Args,
+                                   unsigned NumArgs,
+                                   SourceLocation RParenLoc) {
+  void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) +
+                         sizeof(Expr *) * NumArgs);
+  return new (Mem) CXXUnresolvedConstructExpr(TyBegin, T, LParenLoc,
+                                              Args, NumArgs, RParenLoc);
+}
+
+Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() {
+  return child_iterator(reinterpret_cast<Stmt **>(this + 1));
+}
+
+Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() {
+  return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs);
+}
 
 //===----------------------------------------------------------------------===//
 //  Cloners
index 380634daf3bd491a33de7446f618f14b3fe004fe..30de402edd6519e7a17299be01e1b1741fcce147 100644 (file)
@@ -1110,6 +1110,21 @@ void StmtPrinter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
   PrintExpr(E->getSubExpr());
 }
 
+void 
+StmtPrinter::VisitCXXUnresolvedConstructExpr(
+                                           CXXUnresolvedConstructExpr *Node) {
+  OS << Node->getTypeAsWritten().getAsString();
+  OS << "(";
+  for (CXXUnresolvedConstructExpr::arg_iterator Arg = Node->arg_begin(),
+                                             ArgEnd = Node->arg_end(); 
+       Arg != ArgEnd; ++Arg) {
+    if (Arg != Node->arg_begin())
+      OS << ", ";
+    PrintExpr(*Arg);
+  }
+  OS << ")";
+}
+
 static const char *getTypeTraitName(UnaryTypeTrait UTT) {
   switch (UTT) {
   default: assert(false && "Unknown type trait");
index 30a7598ec62253e01cb785513243c24ef8508376..b9575101b0ae2747ec7e1804c51095208fe241f5 100644 (file)
@@ -164,14 +164,11 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
       CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
     exprs.release();
     
-    // FIXME: Is this correct (I don't think so). Instead, we should have an 
-    // CXXUnresolvedTemporaryObjectExpr node for this.
-    CXXTempVarDecl *Temp = CXXTempVarDecl::Create(Context, CurContext, Ty);
-
-    return Owned(new (Context) CXXTemporaryObjectExpr(Context, Temp, 0, Ty, 
-                                                      TyBeginLoc,
-                                                      Exprs, NumExprs,
-                                                      RParenLoc));
+    return Owned(CXXUnresolvedConstructExpr::Create(Context, 
+                                                    TypeRange.getBegin(), Ty, 
+                                                    LParenLoc,
+                                                    Exprs, NumExprs,
+                                                    RParenLoc));
   }
 
 
index a0e2941e26d382248566c432db85d87632c248c5..1dad862063cce8c8abe30a03640e3709f6860a4d 100644 (file)
@@ -93,6 +93,8 @@ namespace {
     // FIXME: UnaryTypeTraitExpr
     // FIXME: QualifiedDeclRefExpr
     // FIXME: CXXExprWithTemporaries
+    OwningExprResult VisitCXXUnresolvedConstructExpr(
+                                               CXXUnresolvedConstructExpr *E);
     OwningExprResult VisitGNUNullExpr(GNUNullExpr *E);
     OwningExprResult VisitUnresolvedFunctionNameExpr(
                                               UnresolvedFunctionNameExpr *E);
@@ -833,6 +835,45 @@ TemplateExprInstantiator::VisitCXXThisExpr(CXXThisExpr *E) {
   return SemaRef.Owned(TE);
 }
 
+Sema::OwningExprResult 
+TemplateExprInstantiator::VisitCXXUnresolvedConstructExpr(
+                                              CXXUnresolvedConstructExpr *E) {
+  QualType T = SemaRef.InstantiateType(E->getTypeAsWritten(), TemplateArgs,
+                                       E->getTypeBeginLoc(), 
+                                       DeclarationName());
+  if (T.isNull())
+    return SemaRef.ExprError();
+
+  llvm::SmallVector<Expr *, 8> Args;
+  llvm::SmallVector<SourceLocation, 8> FakeCommaLocs;
+  for (CXXUnresolvedConstructExpr::arg_iterator Arg = E->arg_begin(),
+                                             ArgEnd = E->arg_end();
+       Arg != ArgEnd; ++Arg) {
+    OwningExprResult InstArg = Visit(*Arg);
+    if (InstArg.isInvalid()) {
+      for (unsigned I = 0; I != Args.size(); ++I)
+        Args[I]->Destroy(SemaRef.Context);
+      return SemaRef.ExprError();
+    }
+
+    FakeCommaLocs.push_back(
+           SemaRef.PP.getLocForEndOfToken((*Arg)->getSourceRange().getEnd()));
+    Args.push_back(InstArg.takeAs<Expr>());
+  }
+
+  // FIXME: The end of the type range isn't exactly correct.
+  // FIXME: we're faking the locations of the commas
+  return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc(),
+                                                       E->getLParenLoc()),
+                                           T.getAsOpaquePtr(),
+                                           E->getLParenLoc(),
+                                           Sema::MultiExprArg(SemaRef, 
+                                                       (void **)&Args.front(),
+                                                              Args.size()),
+                                           &FakeCommaLocs.front(),
+                                           E->getRParenLoc());
+}
+
 Sema::OwningExprResult 
 Sema::InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
   if (!E)