Removed Sema::VerifyConstantArrayType(). With the new Array/ConstantArray/VariableArray nodes, this
routine was causing more trouble than it was worth. Anders/Chris noticed that it could return an error code
without emiting a diagnostic (which results in an silent invalid decl, which should *never* happen). In addition,
this routine didn't work well for typedefs and field decls. Lastly, it didn't consider that initializers aren't
in place yet.
Added Type::getAsConstantArrayType(), Type::getAsVariableArrayType(), Type::getAsVariablyModifiedType(),
and Type::isVariablyModifiedType();
Modified Sema::ParseDeclarator() and Sema::ParseField() to use the new predicates. Also added a FIXME for
the initializer omission. Also added a missing test for "static" @ file scope.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41647 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index cc0682a..4d2fd4d 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -25,25 +25,6 @@
#include "llvm/ADT/SmallSet.h"
using namespace clang;
-// C99 6.7.2.1p8: Used by ParseDeclarator/ParseField to make sure we have
-// a constant expression. We return true if we don't have a ConstantArrayType.
-bool Sema::VerifyConstantArrayType(const ArrayType *Array,
- SourceLocation DeclLoc) {
- if (const VariableArrayType *VLA = dyn_cast<VariableArrayType>(Array)) {
- Expr *Size = VLA->getSizeExpr();
- if (Size) {
- // FIXME: This emits the diagnostic to enforce 6.7.2.1p8, but the message
- // is wrong. It is also wrong for static variables.
- // FIXME: This is also wrong for:
- // int sub1(int i, char *pi) { typedef int foo[i];
- // struct bar {foo f1; int f2:3; int f3:4} *p; }
- Diag(DeclLoc, diag::err_typecheck_illegal_vla, Size->getSourceRange());
- }
- return true;
- }
- return false;
-}
-
Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
return dyn_cast_or_null<TypedefDecl>(II.getFETokenInfo<Decl>());
}
@@ -305,9 +286,11 @@
if (S->getParent() == 0) {
// C99 6.7.7p2: If a typedef name specifies a variably modified type
// then it shall have block scope.
- if (ArrayType *ary = dyn_cast<ArrayType>(NewTD->getUnderlyingType())) {
- if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
- InvalidDecl = true;
+ if (const VariableArrayType *VAT =
+ NewTD->getUnderlyingType()->getAsVariablyModifiedType()) {
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla,
+ VAT->getSizeExpr()->getSourceRange());
+ InvalidDecl = true;
}
}
} else if (D.isFunctionDeclarator()) {
@@ -377,11 +360,19 @@
R.getAsString());
InvalidDecl = true;
}
- // C99 6.7.5.2p2: If an identifier is declared to be an object with
- // static storage duration, it shall not have a variable length array.
- if (const ArrayType *ary = R->getAsArrayType()) {
- if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
- InvalidDecl = true;
+ if (SC == VarDecl::Static) {
+ // C99 6.7.5.2p2: If an identifier is declared to be an object with
+ // static storage duration, it shall not have a variable length array.
+ if (const VariableArrayType *VLA = R->getAsVariableArrayType()) {
+ Expr *Size = VLA->getSizeExpr();
+ if (Size || (!Size && !Init)) {
+ // FIXME: Since we don't support initializers yet, we only emit this
+ // error when we don't have an initializer. Once initializers are
+ // implemented, the VLA will change to a CLA.
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla);
+ InvalidDecl = true;
+ }
+ }
}
NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
} else {
@@ -397,9 +388,15 @@
if (SC == VarDecl::Static) {
// C99 6.7.5.2p2: If an identifier is declared to be an object with
// static storage duration, it shall not have a variable length array.
- if (const ArrayType *ary = R->getAsArrayType()) {
- if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
+ if (const VariableArrayType *VLA = R->getAsVariableArrayType()) {
+ Expr *Size = VLA->getSizeExpr();
+ if (Size || (!Size && !Init)) {
+ // FIXME: Since we don't support initializers yet, we only emit this
+ // error when we don't have an initializer. Once initializers are
+ // implemented, the VLA will change to a CLA.
+ Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla);
InvalidDecl = true;
+ }
}
}
NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
@@ -779,14 +776,14 @@
QualType T = GetTypeForDeclarator(D, S);
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
bool InvalidDecl = false;
-
+
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
- if (const ArrayType *ary = T->getAsArrayType()) {
- if (VerifyConstantArrayType(ary, Loc))
- InvalidDecl = true;
+ if (const VariableArrayType *VAT = T->getAsVariablyModifiedType()) {
+ Diag(Loc, diag::err_typecheck_illegal_vla,
+ VAT->getSizeExpr()->getSourceRange());
+ InvalidDecl = true;
}
-
// FIXME: Chain fielddecls together.
FieldDecl *NewFD = new FieldDecl(Loc, II, T, 0);
if (D.getInvalidType() || InvalidDecl)