[cfe-commits] r86136 - in /cfe/trunk: lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/Sema/SemaType.cpp test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Thu Nov 5 07:52:31 PST 2009


Author: cornedbee
Date: Thu Nov  5 09:52:31 2009
New Revision: 86136

URL: http://llvm.org/viewvc/llvm-project?rev=86136&view=rev
Log:
Allow the element type of arrays to be incomplete in C++.
This fixes PR5048. Also fix a bug where zero-sized arrays weren't warned about when the size was unsigned.

Added:
    cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp
Modified:
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

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

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Nov  5 09:52:31 2009
@@ -1395,7 +1395,8 @@
                                           const llvm::APInt &ArySizeIn,
                                           ArrayType::ArraySizeModifier ASM,
                                           unsigned EltTypeQuals) {
-  assert((EltTy->isDependentType() || EltTy->isConstantSizeType()) &&
+  assert((EltTy->isDependentType() ||
+          EltTy->isIncompleteType() || EltTy->isConstantSizeType()) &&
          "Constant array of VLAs is illegal!");
 
   // Convert the array size into a canonical width matching the pointer size for

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

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Thu Nov  5 09:52:31 2009
@@ -550,6 +550,12 @@
     // A tagged type (struct/union/enum/class) is incomplete if the decl is a
     // forward declaration, but not a full definition (C99 6.2.5p22).
     return !cast<TagType>(CanonicalType)->getDecl()->isDefinition();
+  case ConstantArray:
+    // An array is incomplete if its element type is incomplete
+    // (C++ [dcl.array]p1).
+    // We don't handle variable arrays (they're not allowed in C++) or
+    // dependent-sized arrays (dependent types are never treated as incomplete).
+    return cast<ArrayType>(CanonicalType)->getElementType()->isIncompleteType();
   case IncompleteArray:
     // An array of unknown size is an incomplete type (C99 6.2.5p22).
     return true;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Nov  5 09:52:31 2009
@@ -563,9 +563,17 @@
   SourceLocation Loc = Brackets.getBegin();
   // C99 6.7.5.2p1: If the element type is an incomplete or function type,
   // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
-  if (RequireCompleteType(Loc, T,
-                             diag::err_illegal_decl_array_incomplete_type))
-    return QualType();
+  // Not in C++, though. There we only dislike void.
+  if (getLangOptions().CPlusPlus) {
+    if (T->isVoidType()) {
+      Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
+      return QualType();
+    }
+  } else {
+    if (RequireCompleteType(Loc, T,
+                            diag::err_illegal_decl_array_incomplete_type))
+      return QualType();
+  }
 
   if (T->isFunctionType()) {
     Diag(Loc, diag::err_illegal_decl_array_of_functions)
@@ -613,24 +621,24 @@
   } else if (ArraySize->isValueDependent()) {
     T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
   } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
-             (!T->isDependentType() && !T->isConstantSizeType())) {
+             (!T->isDependentType() && !T->isIncompleteType() &&
+              !T->isConstantSizeType())) {
     // Per C99, a variable array is an array with either a non-constant
     // size or an element type that has a non-constant-size
     T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
   } else {
     // C99 6.7.5.2p1: If the expression is a constant expression, it shall
     // have a value greater than zero.
-    if (ConstVal.isSigned()) {
-      if (ConstVal.isNegative()) {
-        Diag(ArraySize->getLocStart(),
-             diag::err_typecheck_negative_array_size)
-          << ArraySize->getSourceRange();
-        return QualType();
-      } else if (ConstVal == 0) {
-        // GCC accepts zero sized static arrays.
-        Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
-          << ArraySize->getSourceRange();
-      }
+    if (ConstVal.isSigned() && ConstVal.isNegative()) {
+      Diag(ArraySize->getLocStart(),
+           diag::err_typecheck_negative_array_size)
+        << ArraySize->getSourceRange();
+      return QualType();
+    }
+    if (ConstVal == 0) {
+      // GCC accepts zero sized static arrays.
+      Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
+        << ArraySize->getSourceRange();
     }
     T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
   }
@@ -1692,8 +1700,12 @@
     return false;
 
   // If we have a class template specialization or a class member of a
-  // class template specialization, try to instantiate it.
-  if (const RecordType *Record = T->getAs<RecordType>()) {
+  // class template specialization, or an array with known size of such,
+  // try to instantiate it.
+  QualType MaybeTemplate = T;
+  if (const ConstantArrayType *Array = T->getAs<ConstantArrayType>())
+    MaybeTemplate = Array->getElementType();
+  if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
     if (ClassTemplateSpecializationDecl *ClassTemplateSpec
           = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
       if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)

Added: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp?rev=86136&view=auto

==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp Thu Nov  5 09:52:31 2009
@@ -0,0 +1,44 @@
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+
+// Simple form
+int ar1[10];
+
+// Element type cannot be:
+// - (cv) void
+volatile void ar2[10]; // expected-error {{incomplete element type 'void volatile'}}
+// - a reference
+int& ar3[10]; // expected-error {{array of references}}
+// - a function type
+typedef void Fn();
+Fn ar4[10]; // expected-error {{array of functions}}
+// - an abstract class
+struct Abstract { virtual void fn() = 0; }; // expected-note {{pure virtual}}
+Abstract ar5[10]; // expected-error {{abstract class}}
+
+// If we have a size, it must be greater than zero.
+int ar6[-1]; // expected-error {{array size is negative}}
+int ar7[0u]; // expected-warning {{zero size arrays are an extension}}
+
+// An array with unknown bound is incomplete.
+int ar8[]; // FIXME: This needs to fail!
+// So is an array with an incomplete element type.
+struct Incomplete; // expected-note {{forward declaration}}
+Incomplete ar9[10]; // expected-error {{incomplete type}}
+// Neither of which should be a problem in situations where no complete type
+// is required. (PR5048)
+void fun(int p1[], Incomplete p2[10]);
+extern int ear1[];
+extern Incomplete ear2[10];
+
+// cv migrates to element type
+typedef const int cint;
+extern cint car1[10];
+typedef int intar[10];
+// thus this is a valid redeclaration
+extern const intar car1;
+
+// Check that instantiation works properly when the element type is a template.
+template <typename T> struct S {
+  typename T::type x; // expected-error {{has no members}}
+};
+S<int> ar10[10]; // expected-note {{requested here}}





More information about the cfe-commits mailing list