[cfe-commits] r63253 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CodeGenTypes.cpp lib/Sema/Sema.h lib/Sema/SemaInit.cpp test/Sema/designated-initializers.c
Douglas Gregor
dgregor at apple.com
Wed Jan 28 15:36:19 PST 2009
Author: dgregor
Date: Wed Jan 28 17:36:17 2009
New Revision: 63253
URL: http://llvm.org/viewvc/llvm-project?rev=63253&view=rev
Log:
Improvements to code-generation and semantic analysis of designated
initializers.
- We now initialize unions properly when a member other than the
first is named by a designated initializer.
- We now provide proper semantic analysis and code generation for
GNU array-range designators *except* that side effects will occur
more than once. We warn about this.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
cfe/trunk/lib/CodeGen/CGExprAgg.cpp
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/Sema/designated-initializers.c
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=63253&r1=63252&r2=63253&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Jan 28 17:36:17 2009
@@ -60,10 +60,8 @@
"initializer overrides prior initialization of this subobject")
DIAG(note_previous_initializer, NOTE,
"previous initialization %select{|with side effects }0is here%select{| (side effects may not occur at run time)}0")
-DIAG(warn_gnu_array_range_designator_unsupported, WARNING,
- "GNU array-range designator extension is unsupported")
-DIAG(warn_designator_into_union_broken_init, WARNING,
- "designated initialization of union member is broken")
+DIAG(warn_gnu_array_range_designator_side_effects, WARNING,
+ "side effects due to the GNU array-range designator extension may occur multiple times")
// Declarations.
DIAG(ext_vla, EXTENSION,
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=63253&r1=63252&r2=63253&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Wed Jan 28 17:36:17 2009
@@ -454,10 +454,17 @@
if (Field->getType()->isIncompleteArrayType())
break;
- if (Field->getIdentifier() == 0) {
- // Initializers can't initialize unnamed fields, e.g. "int : 20;"
+ if (Field->isUnnamedBitfield())
continue;
- }
+
+ // When we're coping with C99 designated initializers into a
+ // union, find the field that has the same type as the expression
+ // we're initializing the union with.
+ if (isUnion && CurInitVal < NumInitElements &&
+ (CGF.getContext().getCanonicalType(Field->getType()) !=
+ CGF.getContext().getCanonicalType(E->getInit(CurInitVal)->getType())))
+ continue;
+
// FIXME: volatility
LValue FieldLoc = CGF.EmitLValueForField(DestPtr, *Field, isUnion,0);
if (CurInitVal < NumInitElements) {
@@ -471,8 +478,6 @@
}
// Unions only initialize one field.
- // (FIXME: things can get weird with designators, but they aren't
- // supported yet.)
if (isUnion)
break;
}
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=63253&r1=63252&r2=63253&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Wed Jan 28 17:36:17 2009
@@ -246,12 +246,22 @@
// first field
int FieldNo = 0; // Field no in RecordDecl
FieldDecl* curField = 0;
+ bool sawAnyFields = false;
for (RecordDecl::field_iterator Field = RD->field_begin(),
FieldEnd = RD->field_end();
Field != FieldEnd; ++Field) {
curField = *Field;
FieldNo++;
- if (curField->getIdentifier())
+
+ if (curField->isUnnamedBitfield())
+ continue;
+
+ // If we have an initializer, find the field whose type is the
+ // same as that initializer. This
+ sawAnyFields = true;
+ if (ILE->getNumInits() > 0 &&
+ CGM.getContext().getCanonicalType(curField->getType()) ==
+ CGM.getContext().getCanonicalType(ILE->getInit(0)->getType()))
break;
}
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=63253&r1=63252&r2=63253&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Wed Jan 28 17:36:17 2009
@@ -518,6 +518,7 @@
Field != FieldEnd; ++Field) {
// The offset should usually be zero, but bitfields could be strange
uint64_t offset = RL.getFieldOffset(curField);
+ CGT.ConvertTypeRecursive(Field->getType());
if (Field->isBitField()) {
Expr *BitWidth = Field->getBitWidth();
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=63253&r1=63252&r2=63253&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jan 28 17:36:17 2009
@@ -1879,7 +1879,8 @@
llvm::APSInt *NextElementIndex,
unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex);
+ unsigned &StructuredIndex,
+ bool FinishSubobjectInit = true);
InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
QualType CurrentObjectType,
InitListExpr *StructuredList,
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=63253&r1=63252&r2=63253&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Jan 28 17:36:17 2009
@@ -500,7 +500,7 @@
CheckSubElementType(IList, Field->getType(), IList->getInit(Index), Index,
StructuredList, StructuredIndex);
- if (DeclType->isUnionType()) // FIXME: designated initializers?
+ if (DeclType->isUnionType())
break;
++Field;
@@ -554,7 +554,8 @@
llvm::APSInt *NextElementIndex,
unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex) {
+ unsigned &StructuredIndex,
+ bool FinishSubobjectInit) {
if (D == DIE->designators_end()) {
// Check the actual initialization for the designated object type.
bool prevHadError = hadError;
@@ -645,13 +646,8 @@
// All of the fields of a union are located at the same place in
// the initializer list.
- // FIXME: Need to tell CodeGen which type to initialize to. ImplicitCastExpr?
- if (RT->getDecl()->isUnion() && FieldIndex != 0) {
- SemaRef->Diag(D->getStartLocation(),
- diag::warn_designator_into_union_broken_init)
- << SourceRange(D->getStartLocation(), DIE->getSourceRange().getEnd());
+ if (RT->getDecl()->isUnion())
FieldIndex = 0;
- }
// Update the designator with the field declaration.
D->setField(*Field);
@@ -682,6 +678,9 @@
return false;
}
+ if (!FinishSubobjectInit)
+ return false;
+
// Check the remaining fields within this class/struct/union subobject.
bool prevHadError = hadError;
CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index,
@@ -713,63 +712,102 @@
}
Expr *IndexExpr = 0;
- llvm::APSInt DesignatedIndex;
- if (D->isArrayDesignator())
+ llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
+ if (D->isArrayDesignator()) {
IndexExpr = DIE->getArrayIndex(*D);
- else {
+
+ bool ConstExpr
+ = IndexExpr->isIntegerConstantExpr(DesignatedStartIndex, SemaRef->Context);
+ assert(ConstExpr && "Expression must be constant"); (void)ConstExpr;
+
+ DesignatedEndIndex = DesignatedStartIndex;
+ } else {
assert(D->isArrayRangeDesignator() && "Need array-range designator");
+
+ bool StartConstExpr
+ = DIE->getArrayRangeStart(*D)->isIntegerConstantExpr(DesignatedStartIndex,
+ SemaRef->Context);
+ assert(StartConstExpr && "Expression must be constant"); (void)StartConstExpr;
+
+ bool EndConstExpr
+ = DIE->getArrayRangeEnd(*D)->isIntegerConstantExpr(DesignatedEndIndex,
+ SemaRef->Context);
+ assert(EndConstExpr && "Expression must be constant"); (void)EndConstExpr;
+
IndexExpr = DIE->getArrayRangeEnd(*D);
- SemaRef->Diag(D->getEllipsisLoc(),
- diag::warn_gnu_array_range_designator_unsupported)
- << SourceRange(D->getLBracketLoc(), D->getRBracketLoc());
+
+ if (DesignatedStartIndex.getZExtValue() != DesignatedEndIndex.getZExtValue())
+ SemaRef->Diag(D->getEllipsisLoc(),
+ diag::warn_gnu_array_range_designator_side_effects)
+ << SourceRange(D->getLBracketLoc(), D->getRBracketLoc());
}
- bool ConstExpr
- = IndexExpr->isIntegerConstantExpr(DesignatedIndex, SemaRef->Context);
- assert(ConstExpr && "Expression must be constant"); (void)ConstExpr;
-
if (isa<ConstantArrayType>(AT)) {
llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
- DesignatedIndex.extOrTrunc(MaxElements.getBitWidth());
- DesignatedIndex.setIsUnsigned(MaxElements.isUnsigned());
- if (DesignatedIndex >= MaxElements) {
+ DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
+ DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
+ DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
+ DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
+ if (DesignatedEndIndex >= MaxElements) {
SemaRef->Diag(IndexExpr->getSourceRange().getBegin(),
diag::err_array_designator_too_large)
- << DesignatedIndex.toString(10) << MaxElements.toString(10)
+ << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
<< IndexExpr->getSourceRange();
++Index;
return true;
}
+ } else {
+ // Make sure the bit-widths and signedness match.
+ if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth())
+ DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
+ else if (DesignatedStartIndex.getBitWidth() < DesignatedEndIndex.getBitWidth())
+ DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
+ DesignatedStartIndex.setIsUnsigned(true);
+ DesignatedEndIndex.setIsUnsigned(true);
}
// Make sure that our non-designated initializer list has space
// for a subobject corresponding to this array element.
- unsigned ElementIndex = DesignatedIndex.getZExtValue();
- if (ElementIndex >= StructuredList->getNumInits())
- StructuredList->resizeInits(SemaRef->Context, ElementIndex + 1);
-
- // Recurse to check later designated subobjects.
- QualType ElementType = AT->getElementType();
- if (CheckDesignatedInitializer(IList, DIE, ++D, ElementType, 0, 0, Index,
- StructuredList, ElementIndex))
- return true;
+ if (DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
+ StructuredList->resizeInits(SemaRef->Context,
+ DesignatedEndIndex.getZExtValue() + 1);
+
+ // Repeatedly perform subobject initializations in the range
+ // [DesignatedStartIndex, DesignatedEndIndex].
+
+ // Move to the next designator
+ unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
+ unsigned OldIndex = Index;
+ ++D;
+ while (DesignatedStartIndex <= DesignatedEndIndex) {
+ // Recurse to check later designated subobjects.
+ QualType ElementType = AT->getElementType();
+ Index = OldIndex;
+ if (CheckDesignatedInitializer(IList, DIE, D, ElementType, 0, 0, Index,
+ StructuredList, ElementIndex,
+ (DesignatedStartIndex == DesignatedEndIndex)))
+ return true;
- // Move to the next index in the array that we'll be initializing.
- ++DesignatedIndex;
- ElementIndex = DesignatedIndex.getZExtValue();
+ // Move to the next index in the array that we'll be initializing.
+ ++DesignatedStartIndex;
+ ElementIndex = DesignatedStartIndex.getZExtValue();
+ }
// If this the first designator, our caller will continue checking
// the rest of this array subobject.
if (IsFirstDesignator) {
if (NextElementIndex)
- *NextElementIndex = DesignatedIndex;
+ *NextElementIndex = DesignatedStartIndex;
StructuredIndex = ElementIndex;
return false;
}
-
+
+ if (!FinishSubobjectInit)
+ return false;
+
// Check the remaining elements within this array subobject.
bool prevHadError = hadError;
- CheckArrayType(IList, CurrentObjectType, DesignatedIndex, true, Index,
+ CheckArrayType(IList, CurrentObjectType, DesignatedStartIndex, true, Index,
StructuredList, ElementIndex);
return hadError && !prevHadError;
}
Modified: cfe/trunk/test/Sema/designated-initializers.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/designated-initializers.c?rev=63253&r1=63252&r2=63253&view=diff
==============================================================================
--- cfe/trunk/test/Sema/designated-initializers.c (original)
+++ cfe/trunk/test/Sema/designated-initializers.c Wed Jan 28 17:36:17 2009
@@ -19,7 +19,7 @@
int iarray3[10] = {
[5 ... 12] = 2 // expected-error{{array designator index (12) exceeds array bounds (10)}}\
- // expected-warning{{GNU array-range designator extension is unsupported}}
+ // expected-warning{{side effects due to the GNU array-range designator extension may occur multiple times}}
};
struct point {
@@ -45,8 +45,8 @@
struct point array2[10] = {
[10].x = 2.0, // expected-error{{array designator index (10) exceeds array bounds (10)}}
- [4 ... 5].y = 2.0, // expected-warning{{GNU array-range designator extension is unsupported}}
- [4 ... 6] = { .x = 3, .y = 4.0 } // expected-warning{{GNU array-range designator extension is unsupported}}
+ [4 ... 5].y = 2.0, // expected-warning{{side effects due to the GNU array-range designator extension may occur multiple times}}
+ [4 ... 6] = { .x = 3, .y = 4.0 } // expected-warning{{side effects due to the GNU array-range designator extension may occur multiple times}}
};
struct point array3[10] = {
@@ -117,7 +117,7 @@
// PR clang/3378
int bitwidth[] = { [(long long int)1] = 5, [(short int)2] = 2 };
int a[]= { [sizeof(int)] = 0 };
-int a2[]= { [0 ... sizeof(int)] = 0 }; // expected-warning{{GNU array-range designator extension is unsupported}}
+int a2[]= { [0 ... sizeof(int)] = 0 }; // expected-warning{{side effects due to the GNU array-range designator extension may occur multiple times}}
// Test warnings about initializers overriding previous initializers
struct X {
@@ -138,4 +138,4 @@
}
// FIXME: we need to
-union { char c; long l; } u1 = { .l = 0xFFFF }; // expected-warning{{designated initialization of union member is broken}}
+union { char c; long l; } u1 = { .l = 0xFFFF };
More information about the cfe-commits
mailing list