[cfe-commits] r89366 - in /cfe/trunk: include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/Sema/SemaInit.cpp test/SemaTemplate/dependent-sized_array.cpp

Douglas Gregor dgregor at apple.com
Thu Nov 19 10:03:26 PST 2009


Author: dgregor
Date: Thu Nov 19 12:03:26 2009
New Revision: 89366

URL: http://llvm.org/viewvc/llvm-project?rev=89366&view=rev
Log:
Cope with an amusingly little anomaly with dependent types and
incomplete array initialization, where we have the following in a
template:

  int a[] = { 1, 2, something-value-dependent };
  // ...
  sizeof(a);

The type of "a" appears to be a non-dependent IncompleteArrayType, but
treating it as such makes the sizeof(a) fail at template definition
time. We now correctly handle this by morphing the IncompleteArrayType
into a DependentSizedArrayType with a NULL expression, indicating that
its size has no corresponding expression (and, therefore, the type is
distinct from others).


Added:
    cfe/trunk/test/SemaTemplate/dependent-sized_array.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Nov 19 12:03:26 2009
@@ -1457,21 +1457,27 @@
 
 /// DependentSizedArrayType - This type represents an array type in
 /// C++ whose size is a value-dependent expression. For example:
-/// @code
+///
+/// \code
 /// template<typename T, int Size>
 /// class array {
 ///   T data[Size];
 /// };
-/// @endcode
+/// \endcode
+///
 /// For these types, we won't actually know what the array bound is
 /// until template instantiation occurs, at which point this will
 /// become either a ConstantArrayType or a VariableArrayType.
 class DependentSizedArrayType : public ArrayType {
   ASTContext &Context;
 
-  /// SizeExpr - An assignment expression that will instantiate to the
+  /// \brief An assignment expression that will instantiate to the
   /// size of the array.
+  ///
+  /// The expression itself might be NULL, in which case the array
+  /// type will have its size deduced from an initializer.
   Stmt *SizeExpr;
+
   /// Brackets - The left and right array brackets.
   SourceRange Brackets;
 

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

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Nov 19 12:03:26 2009
@@ -1460,16 +1460,24 @@
                                                 ArrayType::ArraySizeModifier ASM,
                                                 unsigned EltTypeQuals,
                                                 SourceRange Brackets) {
-  assert((NumElts->isTypeDependent() || NumElts->isValueDependent()) &&
+  assert((!NumElts || NumElts->isTypeDependent() || 
+          NumElts->isValueDependent()) &&
          "Size must be type- or value-dependent!");
 
-  llvm::FoldingSetNodeID ID;
-  DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM,
-                                   EltTypeQuals, NumElts);
-
   void *InsertPos = 0;
-  DependentSizedArrayType *Canon
-    = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
+  DependentSizedArrayType *Canon = 0;
+
+  if (NumElts) {
+    // Dependently-sized array types that do not have a specified
+    // number of elements will have their sizes deduced from an
+    // initializer.
+    llvm::FoldingSetNodeID ID;
+    DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM,
+                                     EltTypeQuals, NumElts);
+
+    Canon = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
+  }
+
   DependentSizedArrayType *New;
   if (Canon) {
     // We already have a canonical version of this array type; use it as
@@ -1483,7 +1491,9 @@
       New = new (*this, TypeAlignment)
         DependentSizedArrayType(*this, EltTy, QualType(),
                                 NumElts, ASM, EltTypeQuals, Brackets);
-      DependentSizedArrayTypes.InsertNode(New, InsertPos);
+
+      if (NumElts)
+        DependentSizedArrayTypes.InsertNode(New, InsertPos);
     } else {
       QualType Canon = getDependentSizedArrayType(CanonEltTy, NumElts,
                                                   ASM, EltTypeQuals,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Nov 19 12:03:26 2009
@@ -136,8 +136,29 @@
                                  SourceLocation InitLoc,
                                  DeclarationName InitEntity, bool DirectInit) {
   if (DeclType->isDependentType() ||
-      Init->isTypeDependent() || Init->isValueDependent())
+      Init->isTypeDependent() || Init->isValueDependent()) {
+    // We have either a dependent type or a type- or value-dependent
+    // initializer, so we don't perform any additional checking at
+    // this point.
+
+    // If the declaration is a non-dependent, incomplete array type
+    // that has an initializer, then its type will be completed once
+    // the initializer is instantiated, meaning that the type is
+    // dependent. Morph the declaration's type into a
+    // dependently-sized array type.
+    if (!DeclType->isDependentType()) {
+      if (const IncompleteArrayType *ArrayT
+                           = Context.getAsIncompleteArrayType(DeclType)) {
+        DeclType = Context.getDependentSizedArrayType(ArrayT->getElementType(),
+                                                      /*NumElts=*/0,
+                                                     ArrayT->getSizeModifier(),
+                                           ArrayT->getIndexTypeCVRQualifiers(),
+                                                      SourceRange());
+      }
+    }
+
     return false;
+  }
 
   // C++ [dcl.init.ref]p1:
   //   A variable declared to be a T& or T&&, that is "reference to type T"

Added: cfe/trunk/test/SemaTemplate/dependent-sized_array.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-sized_array.cpp?rev=89366&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/dependent-sized_array.cpp (added)
+++ cfe/trunk/test/SemaTemplate/dependent-sized_array.cpp Thu Nov 19 12:03:26 2009
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<int N>
+void f() {
+  int a[] = { 1, 2, 3, N };
+  unsigned numAs = sizeof(a) / sizeof(int);
+}
+
+template void f<17>();
+

Propchange: cfe/trunk/test/SemaTemplate/dependent-sized_array.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaTemplate/dependent-sized_array.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaTemplate/dependent-sized_array.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list