[cfe-commits] r39296 - in /cfe/cfe/trunk: AST/SemaDecl.cpp AST/SemaType.cpp AST/Type.cpp Sema/SemaDecl.cpp Sema/SemaType.cpp include/clang/AST/Decl.h include/clang/AST/Type.h include/clang/Basic/DiagnosticKinds.def
sabre at cs.uiuc.edu
sabre at cs.uiuc.edu
Wed Jul 11 09:42:39 PDT 2007
Author: sabre
Date: Wed Jul 11 11:42:38 2007
New Revision: 39296
URL: http://llvm.org/viewvc/llvm-project?rev=39296&view=rev
Log:
Enforce the rest of C99 6.7.2.1p2, emitting diagnostics like:
t.c:10:15: warning: 'bonk' may not be nested in a struct due to flexible array member
struct bink bonk;
^
t.c:13:14: error: 'struct bink' may not be used as an array element due to flexible array member
struct bink A[123];
^
for:
struct bink {
struct bink *a;
int X[]; // ok.
};
struct foo {
int A;
struct bink bonk;
};
struct bink A[123];
Modified:
cfe/cfe/trunk/AST/SemaDecl.cpp
cfe/cfe/trunk/AST/SemaType.cpp
cfe/cfe/trunk/AST/Type.cpp
cfe/cfe/trunk/Sema/SemaDecl.cpp
cfe/cfe/trunk/Sema/SemaType.cpp
cfe/cfe/trunk/include/clang/AST/Decl.h
cfe/cfe/trunk/include/clang/AST/Type.h
cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
Modified: cfe/cfe/trunk/AST/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaDecl.cpp?rev=39296&r1=39295&r2=39296&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/AST/SemaDecl.cpp Wed Jul 11 11:42:38 2007
@@ -332,10 +332,15 @@
// Otherwise, if this is the first time we've seen this tag, create the decl.
TagDecl *New;
- if (Kind != Decl::Enum)
+ switch (Kind) {
+ default: assert(0 && "Unknown tag kind!");
+ case Decl::Enum: assert(0 && "Enum tags not implemented yet!");
+ case Decl::Union:
+ case Decl::Struct:
+ case Decl::Class:
New = new RecordDecl(Kind, Loc, Name);
- else
- assert(0 && "Enum tags not implemented yet!");
+ break;
+ }
//if (TK == TK_Definition)
// New->setDefinition(true);
@@ -397,9 +402,12 @@
for (unsigned i = 0; i != NumFields; ++i) {
FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i]));
if (!FD) continue; // Already issued a diagnostic.
-
+
+ // Get the type for the field.
+ Type *FDTy = FD->getType()->getCanonicalType();
+
// C99 6.7.2.1p2 - A field may not be a function type.
- if (isa<FunctionType>(FD->getType())) {
+ if (isa<FunctionType>(FDTy)) {
Diag(FD->getLocation(), diag::err_field_declared_as_function,
FD->getName());
delete FD;
@@ -407,23 +415,53 @@
}
// C99 6.7.2.1p2 - A field may not be an incomplete type except...
- if (FD->getType()->isIncompleteType()) {
+ if (FDTy->isIncompleteType()) {
if (i != NumFields-1 || // ... that the last member ...
Record->getKind() != Decl::Struct || // ... of a structure ...
- !isa<ArrayType>(FD->getType())) {//... may have incomplete array type.
+ !isa<ArrayType>(FDTy)) { //... may have incomplete array type.
Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName());
delete FD;
continue;
}
- if (NumNamedMembers < 1) { //... with more than named member ...
+ if (NumNamedMembers < 1) { //... must have more than named member ...
Diag(FD->getLocation(), diag::err_flexible_array_empty_struct,
FD->getName());
delete FD;
continue;
}
- }
-
+ // Okay, we have a legal flexible array member at the end of the struct.
+ cast<RecordDecl>(Record)->setHasFlexibleArrayMember(true);
+ }
+
+
+ /// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the
+ /// field of another structure or the element of an array.
+ if (RecordType *FDTTy = dyn_cast<RecordType>(FDTy)) {
+ if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
+ // If this is a member of a union, then entire union becomes "flexible".
+ if (Record->getKind() == Decl::Union) {
+ cast<RecordDecl>(Record)->setHasFlexibleArrayMember(true);
+ } else {
+ // If this is a struct/class and this is not the last element, reject
+ // it. Note that GCC supports variable sized arrays in the middle of
+ // structures.
+ if (i != NumFields-1) {
+ Diag(FD->getLocation(), diag::err_variable_sized_type_in_struct,
+ FD->getName());
+ delete FD;
+ continue;
+ }
+
+ // We support flexible arrays at the end of structs in other structs
+ // as an extension.
+ Diag(FD->getLocation(), diag::ext_flexible_array_in_struct,
+ FD->getName());
+ cast<RecordDecl>(Record)->setHasFlexibleArrayMember(true);
+ }
+ }
+ }
+
// Keep track of the number of named members.
if (FD->getIdentifier())
++NumNamedMembers;
Modified: cfe/cfe/trunk/AST/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaType.cpp?rev=39296&r1=39295&r2=39296&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/SemaType.cpp (original)
+++ cfe/cfe/trunk/AST/SemaType.cpp Wed Jul 11 11:42:38 2007
@@ -130,6 +130,17 @@
else
ASM = ArrayType::Normal;
+ // If the element type is a struct or union that contains a variadic
+ // array, reject it: C99 6.7.2.1p2.
+ if (RecordType *EltTy = dyn_cast<RecordType>(T->getCanonicalType())) {
+ if (EltTy->getDecl()->hasFlexibleArrayMember()) {
+ std::string Name;
+ T->getAsString(Name);
+ Diag(DeclType.Loc, diag::err_flexible_array_in_array, Name);
+ return TypeRef();
+ }
+ }
+
T = Context.getArrayType(T, ASM, ATI.TypeQuals, ATI.NumElts);
break;
}
Modified: cfe/cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Type.cpp?rev=39296&r1=39295&r2=39296&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/Type.cpp (original)
+++ cfe/cfe/trunk/AST/Type.cpp Wed Jul 11 11:42:38 2007
@@ -75,6 +75,13 @@
}
}
+bool RecordType::classof(const Type *T) {
+ if (const TaggedType *TT = dyn_cast<TaggedType>(T))
+ return isa<RecordDecl>(TT->getDecl());
+ return false;
+}
+
+
//===----------------------------------------------------------------------===//
// Type Printing
//===----------------------------------------------------------------------===//
Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39296&r1=39295&r2=39296&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:42:38 2007
@@ -332,10 +332,15 @@
// Otherwise, if this is the first time we've seen this tag, create the decl.
TagDecl *New;
- if (Kind != Decl::Enum)
+ switch (Kind) {
+ default: assert(0 && "Unknown tag kind!");
+ case Decl::Enum: assert(0 && "Enum tags not implemented yet!");
+ case Decl::Union:
+ case Decl::Struct:
+ case Decl::Class:
New = new RecordDecl(Kind, Loc, Name);
- else
- assert(0 && "Enum tags not implemented yet!");
+ break;
+ }
//if (TK == TK_Definition)
// New->setDefinition(true);
@@ -397,9 +402,12 @@
for (unsigned i = 0; i != NumFields; ++i) {
FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i]));
if (!FD) continue; // Already issued a diagnostic.
-
+
+ // Get the type for the field.
+ Type *FDTy = FD->getType()->getCanonicalType();
+
// C99 6.7.2.1p2 - A field may not be a function type.
- if (isa<FunctionType>(FD->getType())) {
+ if (isa<FunctionType>(FDTy)) {
Diag(FD->getLocation(), diag::err_field_declared_as_function,
FD->getName());
delete FD;
@@ -407,23 +415,53 @@
}
// C99 6.7.2.1p2 - A field may not be an incomplete type except...
- if (FD->getType()->isIncompleteType()) {
+ if (FDTy->isIncompleteType()) {
if (i != NumFields-1 || // ... that the last member ...
Record->getKind() != Decl::Struct || // ... of a structure ...
- !isa<ArrayType>(FD->getType())) {//... may have incomplete array type.
+ !isa<ArrayType>(FDTy)) { //... may have incomplete array type.
Diag(FD->getLocation(), diag::err_field_incomplete, FD->getName());
delete FD;
continue;
}
- if (NumNamedMembers < 1) { //... with more than named member ...
+ if (NumNamedMembers < 1) { //... must have more than named member ...
Diag(FD->getLocation(), diag::err_flexible_array_empty_struct,
FD->getName());
delete FD;
continue;
}
- }
-
+ // Okay, we have a legal flexible array member at the end of the struct.
+ cast<RecordDecl>(Record)->setHasFlexibleArrayMember(true);
+ }
+
+
+ /// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the
+ /// field of another structure or the element of an array.
+ if (RecordType *FDTTy = dyn_cast<RecordType>(FDTy)) {
+ if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
+ // If this is a member of a union, then entire union becomes "flexible".
+ if (Record->getKind() == Decl::Union) {
+ cast<RecordDecl>(Record)->setHasFlexibleArrayMember(true);
+ } else {
+ // If this is a struct/class and this is not the last element, reject
+ // it. Note that GCC supports variable sized arrays in the middle of
+ // structures.
+ if (i != NumFields-1) {
+ Diag(FD->getLocation(), diag::err_variable_sized_type_in_struct,
+ FD->getName());
+ delete FD;
+ continue;
+ }
+
+ // We support flexible arrays at the end of structs in other structs
+ // as an extension.
+ Diag(FD->getLocation(), diag::ext_flexible_array_in_struct,
+ FD->getName());
+ cast<RecordDecl>(Record)->setHasFlexibleArrayMember(true);
+ }
+ }
+ }
+
// Keep track of the number of named members.
if (FD->getIdentifier())
++NumNamedMembers;
Modified: cfe/cfe/trunk/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaType.cpp?rev=39296&r1=39295&r2=39296&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/SemaType.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaType.cpp Wed Jul 11 11:42:38 2007
@@ -130,6 +130,17 @@
else
ASM = ArrayType::Normal;
+ // If the element type is a struct or union that contains a variadic
+ // array, reject it: C99 6.7.2.1p2.
+ if (RecordType *EltTy = dyn_cast<RecordType>(T->getCanonicalType())) {
+ if (EltTy->getDecl()->hasFlexibleArrayMember()) {
+ std::string Name;
+ T->getAsString(Name);
+ Diag(DeclType.Loc, diag::err_flexible_array_in_array, Name);
+ return TypeRef();
+ }
+ }
+
T = Context.getArrayType(T, ASM, ATI.TypeQuals, ATI.NumElts);
break;
}
Modified: cfe/cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Decl.h?rev=39296&r1=39295&r2=39296&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Decl.h Wed Jul 11 11:42:38 2007
@@ -238,11 +238,19 @@
/// RecordDecl - Represents a struct/union/class.
class RecordDecl : public TagDecl {
+ /// HasFlexibleArrayMember - This is true if this struct ends with a flexible
+ /// array member (e.g. int X[]) or if this union contains a struct that does.
+ /// If so, this cannot be contained in arrays or other structs as a member.
+ bool HasFlexibleArrayMember;
public:
RecordDecl(Kind DK, SourceLocation L, IdentifierInfo *Id) :TagDecl(DK, L, Id){
+ HasFlexibleArrayMember = false;
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
}
+ bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
+ void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
+
static bool classof(const Decl *D) {
return D->getKind() == Struct || D->getKind() == Union ||
D->getKind() == Class;
@@ -250,7 +258,6 @@
static bool classof(const RecordDecl *D) { return true; }
};
-
} // end namespace clang
} // end namespace llvm
Modified: cfe/cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Type.h?rev=39296&r1=39295&r2=39296&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Type.h Wed Jul 11 11:42:38 2007
@@ -22,9 +22,11 @@
namespace llvm {
namespace clang {
class ASTContext;
+ class Type;
class TypeDecl;
class TagDecl;
- class Type;
+ class RecordDecl;
+ class EnumDecl;
/// TypeRef - For efficiency, we don't store CVR-qualified types as nodes on
/// their own: instead each reference to a type stores the qualifiers. This
@@ -387,6 +389,19 @@
static bool classof(const TaggedType *) { return true; }
};
+/// RecordType - This is a helper class that allows the use of isa/cast/dyncast
+/// to detect TaggedType objects of structs/unions/classes.
+class RecordType : public TaggedType {
+ RecordType(); // DO NOT IMPLEMENT
+public:
+
+ RecordDecl *getDecl() const {
+ return reinterpret_cast<RecordDecl*>(TaggedType::getDecl());
+ }
+
+ static bool classof(const Type *T);
+ static bool classof(const RecordType *) { return true; }
+};
/// ...
Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39296&r1=39295&r2=39296&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:42:38 2007
@@ -441,8 +441,14 @@
"field '%s' declared as a function")
DIAG(err_field_incomplete, ERROR,
"field '%s' has incomplete type")
+DIAG(err_variable_sized_type_in_struct, EXTENSION,
+ "variable sized type '%s' must be at end of struct or class")
DIAG(err_flexible_array_empty_struct, ERROR,
"flexible array '%s' not allowed in otherwise empty struct")
+DIAG(ext_flexible_array_in_struct, EXTENSION,
+ "'%s' may not be nested in a struct due to flexible array member")
+DIAG(err_flexible_array_in_array, ERROR,
+ "'%s' may not be used as an array element due to flexible array member")
// Expressions.
DIAG(ext_sizeof_function_type, EXTENSION,
More information about the cfe-commits
mailing list