forked from OSchip/llvm-project
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. llvm-svn: 41647
This commit is contained in:
parent
527ec81d8b
commit
096dd942cf
|
@ -125,7 +125,7 @@ const ReferenceType *Type::getAsReferenceType() const {
|
|||
}
|
||||
|
||||
const ArrayType *Type::getAsArrayType() const {
|
||||
// If this is directly a reference type, return it.
|
||||
// If this is directly an array type, return it.
|
||||
if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
|
||||
return ATy;
|
||||
|
||||
|
@ -136,6 +136,48 @@ const ArrayType *Type::getAsArrayType() const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
const ConstantArrayType *Type::getAsConstantArrayType() const {
|
||||
// If this is directly a constant array type, return it.
|
||||
if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
|
||||
return ATy;
|
||||
|
||||
// If this is a typedef for an array type, strip the typedef off without
|
||||
// losing all typedef information.
|
||||
if (isa<ConstantArrayType>(CanonicalType))
|
||||
return cast<ConstantArrayType>(cast<TypedefType>(this)->LookThroughTypedefs());
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VariableArrayType *Type::getAsVariableArrayType() const {
|
||||
// If this is directly a variable array type, return it.
|
||||
if (const VariableArrayType *ATy = dyn_cast<VariableArrayType>(this))
|
||||
return ATy;
|
||||
|
||||
// If this is a typedef for an array type, strip the typedef off without
|
||||
// losing all typedef information.
|
||||
if (isa<VariableArrayType>(CanonicalType))
|
||||
return cast<VariableArrayType>(cast<TypedefType>(this)->LookThroughTypedefs());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
|
||||
/// types that have a non-constant expression. This does not include "[]".
|
||||
bool Type::isVariablyModifiedType() const {
|
||||
if (const VariableArrayType *VAT = getAsVariableArrayType()) {
|
||||
if (VAT->getSizeExpr())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const VariableArrayType *Type::getAsVariablyModifiedType() const {
|
||||
if (const VariableArrayType *VAT = getAsVariableArrayType()) {
|
||||
if (VAT->getSizeExpr())
|
||||
return VAT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const RecordType *Type::getAsRecordType() const {
|
||||
// If this is directly a reference type, return it.
|
||||
if (const RecordType *RTy = dyn_cast<RecordType>(this))
|
||||
|
|
|
@ -439,12 +439,6 @@ private:
|
|||
QualType CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc,
|
||||
IdentifierInfo &Comp, SourceLocation CmpLoc);
|
||||
|
||||
/// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
|
||||
/// a constant expression of type int with a value greater than zero. If the
|
||||
/// array has an incomplete type or a valid constant size, return false,
|
||||
/// otherwise emit a diagnostic and return true.
|
||||
bool VerifyConstantArrayType(const ArrayType *ary, SourceLocation loc);
|
||||
|
||||
/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
|
||||
/// the specified width and sign. If an overflow occurs, detect it and emit
|
||||
/// the specified diagnostic.
|
||||
|
|
|
@ -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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
|
|||
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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
|
|||
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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
|
|||
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 @@ Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl,
|
|||
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)
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace clang {
|
|||
class ReferenceType;
|
||||
class VectorType;
|
||||
class ArrayType;
|
||||
class ConstantArrayType;
|
||||
class VariableArrayType;
|
||||
class RecordType;
|
||||
class ComplexType;
|
||||
class TagType;
|
||||
|
@ -233,6 +235,10 @@ public:
|
|||
/// routine will need to determine if the size is actually required.
|
||||
bool isIncompleteType() const;
|
||||
|
||||
/// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
|
||||
/// types that have a non-constant expression. This does not include "[]".
|
||||
bool isVariablyModifiedType() const;
|
||||
|
||||
/// Helper methods to distinguish type categories. All type predicates
|
||||
/// operate on the canonical type, ignoring typedefs.
|
||||
bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum)
|
||||
|
@ -271,6 +277,9 @@ public:
|
|||
const PointerType *getAsPointerType() const;
|
||||
const ReferenceType *getAsReferenceType() const;
|
||||
const ArrayType *getAsArrayType() const;
|
||||
const ConstantArrayType *getAsConstantArrayType() const;
|
||||
const VariableArrayType *getAsVariableArrayType() const;
|
||||
const VariableArrayType *getAsVariablyModifiedType() const;
|
||||
const RecordType *getAsRecordType() const;
|
||||
const RecordType *getAsStructureType() const;
|
||||
const RecordType *getAsUnionType() const;
|
||||
|
|
|
@ -39,3 +39,13 @@ void check_size() {
|
|||
int zero_size[0]; // expected-warning{{zero size arrays are an extension}}
|
||||
}
|
||||
|
||||
static int I;
|
||||
typedef int TA[I]; // expected-error {{variable length array declared outside of any function}}
|
||||
|
||||
void strFunc(char *);
|
||||
const char staticAry[] = "test";
|
||||
int checkStaticAry() {
|
||||
strFunc(staticAry); // expected-warning{{passing 'char const []' to 'char *' discards qualifiers}}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue