[cfe-commits] r72233 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/fun-template-def.cpp test/SemaTemplate/instantiate-c99.cpp

Douglas Gregor dgregor at apple.com
Thu May 21 16:17:50 PDT 2009


Author: dgregor
Date: Thu May 21 18:17:49 2009
New Revision: 72233

URL: http://llvm.org/viewvc/llvm-project?rev=72233&view=rev
Log:
Template instantiation for C99 designated initializers, because we
can. Also, delay semantic analysis of initialization for
value-dependent as well as type-dependent expressions, since we can't
always properly type-check a value-dependent expression.

Added:
    cfe/trunk/test/SemaTemplate/instantiate-c99.cpp
Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
    cfe/trunk/test/SemaTemplate/fun-template-def.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu May 21 18:17:49 2009
@@ -41,6 +41,7 @@
 class Expr : public Stmt {
   QualType TR;
 
+protected:
   /// TypeDependent - Whether this expression is type-dependent 
   /// (C++ [temp.dep.expr]).
   bool TypeDependent : 1;
@@ -49,7 +50,6 @@
   /// (C++ [temp.dep.constexpr]).
   bool ValueDependent : 1;
 
-protected:
   // FIXME: Eventually, this constructor should go away and we should
   // require every subclass to provide type/value-dependence
   // information.
@@ -2074,7 +2074,8 @@
   DesignatedInitExpr(QualType Ty, unsigned NumDesignators, 
                      const Designator *Designators,
                      SourceLocation EqualOrColonLoc, bool GNUSyntax,
-                     unsigned NumSubExprs);
+                     Expr **IndexExprs, unsigned NumIndexExprs,
+                     Expr *Init);
 
   explicit DesignatedInitExpr(unsigned NumSubExprs)
     : Expr(DesignatedInitExprClass, EmptyShell()),
@@ -2337,6 +2338,8 @@
     return SourceRange();
   }
 
+  ImplicitValueInitExpr *Clone(ASTContext &C) const;
+
   // Iterators
   virtual child_iterator child_begin();
   virtual child_iterator child_end(); 

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

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu May 21 18:17:49 2009
@@ -385,7 +385,9 @@
 InitListExpr::InitListExpr(SourceLocation lbraceloc, 
                            Expr **initExprs, unsigned numInits,
                            SourceLocation rbraceloc)
-  : Expr(InitListExprClass, QualType()),
+  : Expr(InitListExprClass, QualType(),
+         hasAnyTypeDependentArguments(initExprs, numInits),
+         hasAnyValueDependentArguments(initExprs, numInits)),
     LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0), 
     UnionFieldInit(0), HadArrayRangeDesignator(false) {
 
@@ -1632,13 +1634,48 @@
                                        const Designator *Designators,
                                        SourceLocation EqualOrColonLoc, 
                                        bool GNUSyntax,
-                                       unsigned NumSubExprs)
-  : Expr(DesignatedInitExprClass, Ty), 
+                                       Expr **IndexExprs, 
+                                       unsigned NumIndexExprs,
+                                       Expr *Init)
+  : Expr(DesignatedInitExprClass, Ty, 
+         Init->isTypeDependent(), Init->isValueDependent()),
     EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax), 
-    NumDesignators(NumDesignators), NumSubExprs(NumSubExprs) { 
+    NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) { 
   this->Designators = new Designator[NumDesignators];
-  for (unsigned I = 0; I != NumDesignators; ++I)
+
+  // Record the initializer itself.
+  child_iterator Child = child_begin();
+  *Child++ = Init;
+
+  // Copy the designators and their subexpressions, computing
+  // value-dependence along the way.
+  unsigned IndexIdx = 0;
+  for (unsigned I = 0; I != NumDesignators; ++I) {
     this->Designators[I] = Designators[I];
+
+    if (this->Designators[I].isArrayDesignator()) {
+      // Compute type- and value-dependence.
+      Expr *Index = IndexExprs[IndexIdx];
+      ValueDependent = ValueDependent || 
+        Index->isTypeDependent() || Index->isValueDependent();
+
+      // Copy the index expressions into permanent storage.
+      *Child++ = IndexExprs[IndexIdx++];
+    } else if (this->Designators[I].isArrayRangeDesignator()) {
+      // Compute type- and value-dependence.
+      Expr *Start = IndexExprs[IndexIdx];
+      Expr *End = IndexExprs[IndexIdx + 1];
+      ValueDependent = ValueDependent || 
+        Start->isTypeDependent() || Start->isValueDependent() ||
+        End->isTypeDependent() || End->isValueDependent();
+
+      // Copy the start/end expressions into permanent storage.
+      *Child++ = IndexExprs[IndexIdx++];
+      *Child++ = IndexExprs[IndexIdx++];
+    }
+  }
+
+  assert(IndexIdx == NumIndexExprs && "Wrong number of index expressions");
 }
 
 DesignatedInitExpr *
@@ -1649,29 +1686,9 @@
                            bool UsesColonSyntax, Expr *Init) {
   void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
                          sizeof(Stmt *) * (NumIndexExprs + 1), 8);
-  DesignatedInitExpr *DIE 
-    = new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, Designators,
-                                   ColonOrEqualLoc, UsesColonSyntax,
-                                   NumIndexExprs + 1);
-
-  // Fill in the designators
-  unsigned ExpectedNumSubExprs = 0;
-  designators_iterator Desig = DIE->designators_begin();
-  for (unsigned Idx = 0; Idx < NumDesignators; ++Idx, ++Desig) {
-    if (Designators[Idx].isArrayDesignator())
-      ++ExpectedNumSubExprs;
-    else if (Designators[Idx].isArrayRangeDesignator())
-      ExpectedNumSubExprs += 2;
-  }
-  assert(ExpectedNumSubExprs == NumIndexExprs && "Wrong number of indices!");
-
-  // Fill in the subexpressions, including the initializer expression.
-  child_iterator Child = DIE->child_begin();
-  *Child++ = Init;
-  for (unsigned Idx = 0; Idx < NumIndexExprs; ++Idx, ++Child)
-    *Child = IndexExprs[Idx];
-
-  return DIE;
+  return new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, Designators,
+                                      ColonOrEqualLoc, UsesColonSyntax,
+                                      IndexExprs, NumIndexExprs, Init);
 }
 
 DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C, 
@@ -1766,6 +1783,10 @@
   Expr::Destroy(C);
 }
 
+ImplicitValueInitExpr *ImplicitValueInitExpr::Clone(ASTContext &C) const {
+  return new (C) ImplicitValueInitExpr(getType());
+}
+
 //===----------------------------------------------------------------------===//
 //  ExprIterator.
 //===----------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu May 21 18:17:49 2009
@@ -117,7 +117,8 @@
                                  SourceLocation InitLoc,
                                  DeclarationName InitEntity,
                                  bool DirectInit) {
-  if (DeclType->isDependentType() || Init->isTypeDependent())
+  if (DeclType->isDependentType() || 
+      Init->isTypeDependent() || Init->isValueDependent())
     return false;
   
   // C++ [dcl.init.ref]p1:
@@ -1635,7 +1636,9 @@
     case Designator::ArrayDesignator: {
       Expr *Index = static_cast<Expr *>(D.getArrayIndex());
       llvm::APSInt IndexValue;
-      if (CheckArrayDesignatorExpr(*this, Index, IndexValue))
+      if (!Index->isTypeDependent() &&
+          !Index->isValueDependent() &&
+          CheckArrayDesignatorExpr(*this, Index, IndexValue))
         Invalid = true;
       else {
         Designators.push_back(ASTDesignator(InitExpressions.size(),
@@ -1651,12 +1654,20 @@
       Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd());
       llvm::APSInt StartValue;
       llvm::APSInt EndValue;
-      if (CheckArrayDesignatorExpr(*this, StartIndex, StartValue) ||
-          CheckArrayDesignatorExpr(*this, EndIndex, EndValue))
+      bool StartDependent = StartIndex->isTypeDependent() ||
+                            StartIndex->isValueDependent();
+      bool EndDependent = EndIndex->isTypeDependent() ||
+                          EndIndex->isValueDependent();
+      if ((!StartDependent &&
+           CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) ||
+          (!EndDependent &&
+           CheckArrayDesignatorExpr(*this, EndIndex, EndValue)))
         Invalid = true;
       else {
         // Make sure we're comparing values with the same bit width.
-        if (StartValue.getBitWidth() > EndValue.getBitWidth())
+        if (StartDependent || EndDependent) {
+          // Nothing to compute.
+        } else if (StartValue.getBitWidth() > EndValue.getBitWidth())
           EndValue.extend(StartValue.getBitWidth());
         else if (StartValue.getBitWidth() < EndValue.getBitWidth())
           StartValue.extend(EndValue.getBitWidth());

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Thu May 21 18:17:49 2009
@@ -16,6 +16,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/Parse/DeclSpec.h"
+#include "clang/Parse/Designator.h"
 #include "clang/Lex/Preprocessor.h" // for the identifier table
 #include "llvm/Support/Compiler.h"
 using namespace clang;
@@ -61,8 +62,8 @@
     OwningExprResult VisitChooseExpr(ChooseExpr *E);
     OwningExprResult VisitVAArgExpr(VAArgExpr *E);
     OwningExprResult VisitInitListExpr(InitListExpr *E);
-    // FIXME: DesignatedInitExpr
-    // FIXME: ImplicitValueInitExpr
+    OwningExprResult VisitDesignatedInitExpr(DesignatedInitExpr *E);
+    OwningExprResult VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
     // FIXME: ExtVectorElementExpr
     // FIXME: BlockExpr
     // FIXME: BlockDeclRefExpr
@@ -595,6 +596,62 @@
 }
 
 Sema::OwningExprResult 
+TemplateExprInstantiator::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+  Designation Desig;
+
+  // Instantiate the initializer value
+  OwningExprResult Init = Visit(E->getInit());
+  if (Init.isInvalid())
+    return SemaRef.ExprError();
+
+  // Instantiate the designators.
+  ExprVector ArrayExprs(SemaRef); // Expresses used in array designators
+  for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
+                                             DEnd = E->designators_end();
+       D != DEnd; ++D) {
+    if (D->isFieldDesignator()) {
+      Desig.AddDesignator(Designator::getField(D->getFieldName(),
+                                               D->getDotLoc(),
+                                               D->getFieldLoc()));
+      continue;
+    }
+
+    if (D->isArrayDesignator()) {
+      OwningExprResult Index = Visit(E->getArrayIndex(*D));
+      if (Index.isInvalid())
+        return SemaRef.ExprError();
+
+      Desig.AddDesignator(Designator::getArray(Index.get(), 
+                                               D->getLBracketLoc()));
+
+      ArrayExprs.push_back(Index.release());
+      continue;
+    }
+
+    assert(false && "No array range designators, yet");
+  }
+
+  OwningExprResult Result = 
+    SemaRef.ActOnDesignatedInitializer(Desig,
+                                       E->getEqualOrColonLoc(),
+                                       E->usesGNUSyntax(),
+                                       move(Init));
+  if (Result.isInvalid())
+    return SemaRef.ExprError();
+
+  ArrayExprs.take();
+  return move(Result);
+}
+
+Sema::OwningExprResult 
+TemplateExprInstantiator::VisitImplicitValueInitExpr(
+                                                  ImplicitValueInitExpr *E) {
+  assert(!E->isTypeDependent() && !E->isValueDependent() &&
+         "ImplicitValueInitExprs are never dependent");
+  return SemaRef.Clone(E);
+}
+
+Sema::OwningExprResult 
 TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
   bool isSizeOf = E->isSizeOf();
 

Modified: cfe/trunk/test/SemaTemplate/fun-template-def.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/fun-template-def.cpp?rev=72233&r1=72232&r2=72233&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/fun-template-def.cpp (original)
+++ cfe/trunk/test/SemaTemplate/fun-template-def.cpp Thu May 21 18:17:49 2009
@@ -34,9 +34,9 @@
   new (t1, u1) int;
   delete t1;
 
-  dummy d1 = sizeof(t1); // expected-error {{cannot initialize 'd1'}}
+  dummy d1 = sizeof(t1); // FIXME: delayed checking okay?
   dummy d2 = offsetof(T, foo); // expected-error {{cannot initialize 'd2'}}
-  dummy d3 = __alignof(u1); // expected-error {{cannot initialize 'd3'}}
+  dummy d3 = __alignof(u1); // FIXME: delayed checking okay?
   i1 = typeid(t1); // expected-error {{incompatible type assigning}}
 
   return u1;

Added: cfe/trunk/test/SemaTemplate/instantiate-c99.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-c99.cpp?rev=72233&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-c99.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-c99.cpp Thu May 21 18:17:49 2009
@@ -0,0 +1,56 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Test template instantiation for C99-specific features.
+
+// ---------------------------------------------------------------------
+// Designated initializers
+// ---------------------------------------------------------------------
+template<typename T, typename XType, typename YType>
+struct DesigInit0 {
+  void f(XType x, YType y) {
+    T agg = { 
+      .y = y, // expected-error{{does not refer}}
+      .x = x  // expected-error{{does not refer}}
+    };
+  }
+};
+
+struct Point2D {
+  float x, y;
+};
+
+template struct DesigInit0<Point2D, int, double>;
+
+struct Point3D {
+  float x, y, z;
+};
+
+template struct DesigInit0<Point3D, int, double>;
+
+struct Color { 
+  unsigned char red, green, blue;
+};
+
+struct ColorPoint3D {
+  Color color;
+  float x, y, z;
+};
+
+template struct DesigInit0<ColorPoint3D, int, double>;
+template struct DesigInit0<Color, int, double>; // expected-note{{instantiation}}
+
+template<typename T, int Subscript1, int Subscript2,
+         typename Val1, typename Val2>
+struct DesigArrayInit0 {
+  void f(Val1 val1, Val2 val2) {
+    T array = {
+      [Subscript1] = val1,
+      [Subscript2] = val2 // expected-error{{exceeds array bounds}}
+    };
+
+    int array2[10] = { [5] = 3 };
+  }
+};
+
+template struct DesigArrayInit0<int[8], 5, 3, float, int>;
+template struct DesigArrayInit0<int[8], 5, 13, float, int>; // expected-note{{instantiation}}





More information about the cfe-commits mailing list