[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