[cfe-commits] r72176 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Wed May 20 11:46:26 PDT 2009


Author: dgregor
Date: Wed May 20 13:46:25 2009
New Revision: 72176

URL: http://llvm.org/viewvc/llvm-project?rev=72176&view=rev
Log:
Introduce a new expression type, CXXUnresolvedConstructExpr, to
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.


Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/StmtNodes.def
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=72176&r1=72175&r2=72176&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed May 20 13:46:25 2009
@@ -982,6 +982,103 @@
   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

Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=72176&r1=72175&r2=72176&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Wed May 20 13:46:25 2009
@@ -126,6 +126,7 @@
 EXPR(CXXConstructExpr       , Expr)
 EXPR(CXXExprWithTemporaries , Expr)
 EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
+EXPR(CXXUnresolvedConstructExpr, Expr)
 
 // Obj-C Expressions.
 EXPR(ObjCStringLiteral    , Expr)

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=72176&r1=72175&r2=72176&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed May 20 13:46:25 2009
@@ -314,6 +314,45 @@
   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

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=72176&r1=72175&r2=72176&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed May 20 13:46:25 2009
@@ -1110,6 +1110,21 @@
   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");

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=72176&r1=72175&r2=72176&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed May 20 13:46:25 2009
@@ -164,14 +164,11 @@
       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));
   }
 
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=72176&r1=72175&r2=72176&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Wed May 20 13:46:25 2009
@@ -93,6 +93,8 @@
     // FIXME: UnaryTypeTraitExpr
     // FIXME: QualifiedDeclRefExpr
     // FIXME: CXXExprWithTemporaries
+    OwningExprResult VisitCXXUnresolvedConstructExpr(
+                                               CXXUnresolvedConstructExpr *E);
     OwningExprResult VisitGNUNullExpr(GNUNullExpr *E);
     OwningExprResult VisitUnresolvedFunctionNameExpr(
                                               UnresolvedFunctionNameExpr *E);
@@ -834,6 +836,45 @@
 }
 
 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)
     return Owned((Expr *)0);





More information about the cfe-commits mailing list