зеркало из https://github.com/microsoft/clang-1.git
Implement support for designated initializers that refer to members of
anonymous structs or unions. Fixes PR3778. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69153 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
3ac86b59b0
Коммит
ffb4b6e299
|
@ -1963,6 +1963,11 @@ private:
|
||||||
/// designators, one array designator for @c [2] followed by one field
|
/// designators, one array designator for @c [2] followed by one field
|
||||||
/// designator for @c .y. The initalization expression will be 1.0.
|
/// designator for @c .y. The initalization expression will be 1.0.
|
||||||
class DesignatedInitExpr : public Expr {
|
class DesignatedInitExpr : public Expr {
|
||||||
|
public:
|
||||||
|
/// \brief Forward declaration of the Designator class.
|
||||||
|
class Designator;
|
||||||
|
|
||||||
|
private:
|
||||||
/// The location of the '=' or ':' prior to the actual initializer
|
/// The location of the '=' or ':' prior to the actual initializer
|
||||||
/// expression.
|
/// expression.
|
||||||
SourceLocation EqualOrColonLoc;
|
SourceLocation EqualOrColonLoc;
|
||||||
|
@ -1974,17 +1979,20 @@ class DesignatedInitExpr : public Expr {
|
||||||
/// The number of designators in this initializer expression.
|
/// The number of designators in this initializer expression.
|
||||||
unsigned NumDesignators : 15;
|
unsigned NumDesignators : 15;
|
||||||
|
|
||||||
|
/// \brief The designators in this designated initialization
|
||||||
|
/// expression.
|
||||||
|
Designator *Designators;
|
||||||
|
|
||||||
/// The number of subexpressions of this initializer expression,
|
/// The number of subexpressions of this initializer expression,
|
||||||
/// which contains both the initializer and any additional
|
/// which contains both the initializer and any additional
|
||||||
/// expressions used by array and array-range designators.
|
/// expressions used by array and array-range designators.
|
||||||
unsigned NumSubExprs : 16;
|
unsigned NumSubExprs : 16;
|
||||||
|
|
||||||
|
|
||||||
DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
|
DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
|
||||||
|
const Designator *Designators,
|
||||||
SourceLocation EqualOrColonLoc, bool GNUSyntax,
|
SourceLocation EqualOrColonLoc, bool GNUSyntax,
|
||||||
unsigned NumSubExprs)
|
unsigned NumSubExprs);
|
||||||
: Expr(DesignatedInitExprClass, Ty),
|
|
||||||
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
|
|
||||||
NumDesignators(NumDesignators), NumSubExprs(NumSubExprs) { }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// A field designator, e.g., ".x".
|
/// A field designator, e.g., ".x".
|
||||||
|
@ -2041,6 +2049,8 @@ public:
|
||||||
friend class DesignatedInitExpr;
|
friend class DesignatedInitExpr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Designator() {}
|
||||||
|
|
||||||
/// @brief Initializes a field designator.
|
/// @brief Initializes a field designator.
|
||||||
Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
|
Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc,
|
||||||
SourceLocation FieldLoc)
|
SourceLocation FieldLoc)
|
||||||
|
@ -2136,8 +2146,10 @@ public:
|
||||||
|
|
||||||
// Iterator access to the designators.
|
// Iterator access to the designators.
|
||||||
typedef Designator* designators_iterator;
|
typedef Designator* designators_iterator;
|
||||||
designators_iterator designators_begin();
|
designators_iterator designators_begin() { return Designators; }
|
||||||
designators_iterator designators_end();
|
designators_iterator designators_end() {
|
||||||
|
return Designators + NumDesignators;
|
||||||
|
}
|
||||||
|
|
||||||
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
|
Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
|
||||||
|
|
||||||
|
@ -2162,8 +2174,15 @@ public:
|
||||||
*child_begin() = init;
|
*child_begin() = init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Replaces the designator at index @p Idx with the series
|
||||||
|
/// of designators in [First, Last).
|
||||||
|
void ExpandDesignator(unsigned Idx, const Designator *First,
|
||||||
|
const Designator *Last);
|
||||||
|
|
||||||
virtual SourceRange getSourceRange() const;
|
virtual SourceRange getSourceRange() const;
|
||||||
|
|
||||||
|
virtual void Destroy(ASTContext &C);
|
||||||
|
|
||||||
static bool classof(const Stmt *T) {
|
static bool classof(const Stmt *T) {
|
||||||
return T->getStmtClass() == DesignatedInitExprClass;
|
return T->getStmtClass() == DesignatedInitExprClass;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,6 @@ def err_field_designator_unknown : Error<
|
||||||
def err_field_designator_nonfield : Error<
|
def err_field_designator_nonfield : Error<
|
||||||
"field designator %0 does not refer to a non-static data member">;
|
"field designator %0 does not refer to a non-static data member">;
|
||||||
def note_field_designator_found : Note<"field designator refers here">;
|
def note_field_designator_found : Note<"field designator refers here">;
|
||||||
def err_field_designator_anon_class : Error<
|
|
||||||
"field designator %0 refers to a member of an anonymous "
|
|
||||||
"%select{struct|class|union}1">;
|
|
||||||
def err_designator_for_scalar_init : Error<
|
def err_designator_for_scalar_init : Error<
|
||||||
"designator in initializer for scalar type %0">;
|
"designator in initializer for scalar type %0">;
|
||||||
def warn_subobject_initializer_overrides : Warning<
|
def warn_subobject_initializer_overrides : Warning<
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "clang/AST/RecordLayout.h"
|
#include "clang/AST/RecordLayout.h"
|
||||||
#include "clang/AST/StmtVisitor.h"
|
#include "clang/AST/StmtVisitor.h"
|
||||||
#include "clang/Basic/TargetInfo.h"
|
#include "clang/Basic/TargetInfo.h"
|
||||||
|
#include <algorithm>
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -1499,6 +1500,19 @@ IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() {
|
||||||
return getField()->getIdentifier();
|
return getField()->getIdentifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
|
||||||
|
const Designator *Designators,
|
||||||
|
SourceLocation EqualOrColonLoc,
|
||||||
|
bool GNUSyntax,
|
||||||
|
unsigned NumSubExprs)
|
||||||
|
: Expr(DesignatedInitExprClass, Ty),
|
||||||
|
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
|
||||||
|
NumDesignators(NumDesignators), NumSubExprs(NumSubExprs) {
|
||||||
|
this->Designators = new Designator[NumDesignators];
|
||||||
|
for (unsigned I = 0; I != NumDesignators; ++I)
|
||||||
|
this->Designators[I] = Designators[I];
|
||||||
|
}
|
||||||
|
|
||||||
DesignatedInitExpr *
|
DesignatedInitExpr *
|
||||||
DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
|
DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
|
||||||
unsigned NumDesignators,
|
unsigned NumDesignators,
|
||||||
|
@ -1506,10 +1520,9 @@ DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
|
||||||
SourceLocation ColonOrEqualLoc,
|
SourceLocation ColonOrEqualLoc,
|
||||||
bool UsesColonSyntax, Expr *Init) {
|
bool UsesColonSyntax, Expr *Init) {
|
||||||
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
|
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
|
||||||
sizeof(Designator) * NumDesignators +
|
|
||||||
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
|
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
|
||||||
DesignatedInitExpr *DIE
|
DesignatedInitExpr *DIE
|
||||||
= new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators,
|
= new (Mem) DesignatedInitExpr(C.VoidTy, NumDesignators, Designators,
|
||||||
ColonOrEqualLoc, UsesColonSyntax,
|
ColonOrEqualLoc, UsesColonSyntax,
|
||||||
NumIndexExprs + 1);
|
NumIndexExprs + 1);
|
||||||
|
|
||||||
|
@ -1517,7 +1530,6 @@ DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
|
||||||
unsigned ExpectedNumSubExprs = 0;
|
unsigned ExpectedNumSubExprs = 0;
|
||||||
designators_iterator Desig = DIE->designators_begin();
|
designators_iterator Desig = DIE->designators_begin();
|
||||||
for (unsigned Idx = 0; Idx < NumDesignators; ++Idx, ++Desig) {
|
for (unsigned Idx = 0; Idx < NumDesignators; ++Idx, ++Desig) {
|
||||||
new (static_cast<void*>(Desig)) Designator(Designators[Idx]);
|
|
||||||
if (Designators[Idx].isArrayDesignator())
|
if (Designators[Idx].isArrayDesignator())
|
||||||
++ExpectedNumSubExprs;
|
++ExpectedNumSubExprs;
|
||||||
else if (Designators[Idx].isArrayRangeDesignator())
|
else if (Designators[Idx].isArrayRangeDesignator())
|
||||||
|
@ -1549,22 +1561,10 @@ SourceRange DesignatedInitExpr::getSourceRange() const {
|
||||||
return SourceRange(StartLoc, getInit()->getSourceRange().getEnd());
|
return SourceRange(StartLoc, getInit()->getSourceRange().getEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
DesignatedInitExpr::designators_iterator
|
|
||||||
DesignatedInitExpr::designators_begin() {
|
|
||||||
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
|
||||||
Ptr += sizeof(DesignatedInitExpr);
|
|
||||||
return static_cast<Designator*>(static_cast<void*>(Ptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
DesignatedInitExpr::designators_iterator DesignatedInitExpr::designators_end() {
|
|
||||||
return designators_begin() + NumDesignators;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) {
|
Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) {
|
||||||
assert(D.Kind == Designator::ArrayDesignator && "Requires array designator");
|
assert(D.Kind == Designator::ArrayDesignator && "Requires array designator");
|
||||||
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
||||||
Ptr += sizeof(DesignatedInitExpr);
|
Ptr += sizeof(DesignatedInitExpr);
|
||||||
Ptr += sizeof(Designator) * NumDesignators;
|
|
||||||
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
||||||
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
|
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
|
||||||
}
|
}
|
||||||
|
@ -1574,7 +1574,6 @@ Expr *DesignatedInitExpr::getArrayRangeStart(const Designator& D) {
|
||||||
"Requires array range designator");
|
"Requires array range designator");
|
||||||
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
||||||
Ptr += sizeof(DesignatedInitExpr);
|
Ptr += sizeof(DesignatedInitExpr);
|
||||||
Ptr += sizeof(Designator) * NumDesignators;
|
|
||||||
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
||||||
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
|
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
|
||||||
}
|
}
|
||||||
|
@ -1584,11 +1583,43 @@ Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) {
|
||||||
"Requires array range designator");
|
"Requires array range designator");
|
||||||
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
||||||
Ptr += sizeof(DesignatedInitExpr);
|
Ptr += sizeof(DesignatedInitExpr);
|
||||||
Ptr += sizeof(Designator) * NumDesignators;
|
|
||||||
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
||||||
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2));
|
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Replaces the designator at index @p Idx with the series
|
||||||
|
/// of designators in [First, Last).
|
||||||
|
void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
|
||||||
|
const Designator *First,
|
||||||
|
const Designator *Last) {
|
||||||
|
unsigned NumNewDesignators = Last - First;
|
||||||
|
if (NumNewDesignators == 0) {
|
||||||
|
std::copy_backward(Designators + Idx + 1,
|
||||||
|
Designators + NumDesignators,
|
||||||
|
Designators + Idx);
|
||||||
|
--NumNewDesignators;
|
||||||
|
return;
|
||||||
|
} else if (NumNewDesignators == 1) {
|
||||||
|
Designators[Idx] = *First;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Designator *NewDesignators
|
||||||
|
= new Designator[NumDesignators - 1 + NumNewDesignators];
|
||||||
|
std::copy(Designators, Designators + Idx, NewDesignators);
|
||||||
|
std::copy(First, Last, NewDesignators + Idx);
|
||||||
|
std::copy(Designators + Idx + 1, Designators + NumDesignators,
|
||||||
|
NewDesignators + Idx + NumNewDesignators);
|
||||||
|
delete [] Designators;
|
||||||
|
Designators = NewDesignators;
|
||||||
|
NumDesignators = NumDesignators - 1 + NumNewDesignators;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesignatedInitExpr::Destroy(ASTContext &C) {
|
||||||
|
delete [] Designators;
|
||||||
|
Expr::Destroy(C);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ExprIterator.
|
// ExprIterator.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -1774,7 +1805,6 @@ Stmt::child_iterator InitListExpr::child_end() {
|
||||||
Stmt::child_iterator DesignatedInitExpr::child_begin() {
|
Stmt::child_iterator DesignatedInitExpr::child_begin() {
|
||||||
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
||||||
Ptr += sizeof(DesignatedInitExpr);
|
Ptr += sizeof(DesignatedInitExpr);
|
||||||
Ptr += sizeof(Designator) * NumDesignators;
|
|
||||||
return reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
return reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
||||||
}
|
}
|
||||||
Stmt::child_iterator DesignatedInitExpr::child_end() {
|
Stmt::child_iterator DesignatedInitExpr::child_end() {
|
||||||
|
|
|
@ -1226,6 +1226,8 @@ public:
|
||||||
DeclRefExpr *BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
|
DeclRefExpr *BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
|
||||||
bool TypeDependent, bool ValueDependent,
|
bool TypeDependent, bool ValueDependent,
|
||||||
const CXXScopeSpec *SS = 0);
|
const CXXScopeSpec *SS = 0);
|
||||||
|
VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
|
||||||
|
llvm::SmallVectorImpl<FieldDecl *> &Path);
|
||||||
OwningExprResult
|
OwningExprResult
|
||||||
BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
|
BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
|
||||||
FieldDecl *Field,
|
FieldDecl *Field,
|
||||||
|
|
|
@ -486,29 +486,33 @@ static Decl *getObjectForAnonymousRecordDecl(ASTContext &Context,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sema::OwningExprResult
|
/// \brief Given a field that represents a member of an anonymous
|
||||||
Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
|
/// struct/union, build the path from that field's context to the
|
||||||
FieldDecl *Field,
|
/// actual member.
|
||||||
Expr *BaseObjectExpr,
|
///
|
||||||
SourceLocation OpLoc) {
|
/// Construct the sequence of field member references we'll have to
|
||||||
|
/// perform to get to the field in the anonymous union/struct. The
|
||||||
|
/// list of members is built from the field outward, so traverse it
|
||||||
|
/// backwards to go from an object in the current context to the field
|
||||||
|
/// we found.
|
||||||
|
///
|
||||||
|
/// \returns The variable from which the field access should begin,
|
||||||
|
/// for an anonymous struct/union that is not a member of another
|
||||||
|
/// class. Otherwise, returns NULL.
|
||||||
|
VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
|
||||||
|
llvm::SmallVectorImpl<FieldDecl *> &Path) {
|
||||||
assert(Field->getDeclContext()->isRecord() &&
|
assert(Field->getDeclContext()->isRecord() &&
|
||||||
cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion()
|
cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion()
|
||||||
&& "Field must be stored inside an anonymous struct or union");
|
&& "Field must be stored inside an anonymous struct or union");
|
||||||
|
|
||||||
// Construct the sequence of field member references
|
Path.push_back(Field);
|
||||||
// we'll have to perform to get to the field in the anonymous
|
|
||||||
// union/struct. The list of members is built from the field
|
|
||||||
// outward, so traverse it backwards to go from an object in
|
|
||||||
// the current context to the field we found.
|
|
||||||
llvm::SmallVector<FieldDecl *, 4> AnonFields;
|
|
||||||
AnonFields.push_back(Field);
|
|
||||||
VarDecl *BaseObject = 0;
|
VarDecl *BaseObject = 0;
|
||||||
DeclContext *Ctx = Field->getDeclContext();
|
DeclContext *Ctx = Field->getDeclContext();
|
||||||
do {
|
do {
|
||||||
RecordDecl *Record = cast<RecordDecl>(Ctx);
|
RecordDecl *Record = cast<RecordDecl>(Ctx);
|
||||||
Decl *AnonObject = getObjectForAnonymousRecordDecl(Context, Record);
|
Decl *AnonObject = getObjectForAnonymousRecordDecl(Context, Record);
|
||||||
if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject))
|
if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject))
|
||||||
AnonFields.push_back(AnonField);
|
Path.push_back(AnonField);
|
||||||
else {
|
else {
|
||||||
BaseObject = cast<VarDecl>(AnonObject);
|
BaseObject = cast<VarDecl>(AnonObject);
|
||||||
break;
|
break;
|
||||||
|
@ -516,7 +520,19 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
|
||||||
Ctx = Ctx->getParent();
|
Ctx = Ctx->getParent();
|
||||||
} while (Ctx->isRecord() &&
|
} while (Ctx->isRecord() &&
|
||||||
cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion());
|
cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion());
|
||||||
|
|
||||||
|
return BaseObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sema::OwningExprResult
|
||||||
|
Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
|
||||||
|
FieldDecl *Field,
|
||||||
|
Expr *BaseObjectExpr,
|
||||||
|
SourceLocation OpLoc) {
|
||||||
|
llvm::SmallVector<FieldDecl *, 4> AnonFields;
|
||||||
|
VarDecl *BaseObject = BuildAnonymousStructUnionMemberPath(Field,
|
||||||
|
AnonFields);
|
||||||
|
|
||||||
// Build the expression that refers to the base object, from
|
// Build the expression that refers to the base object, from
|
||||||
// which we will build a sequence of member references to each
|
// which we will build a sequence of member references to each
|
||||||
// of the anonymous union objects and, eventually, the field we
|
// of the anonymous union objects and, eventually, the field we
|
||||||
|
|
|
@ -1031,6 +1031,64 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList,
|
||||||
StructuredIndex);
|
StructuredIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Expand a field designator that refers to a member of an
|
||||||
|
/// anonymous struct or union into a series of field designators that
|
||||||
|
/// refers to the field within the appropriate subobject.
|
||||||
|
///
|
||||||
|
/// Field/FieldIndex will be updated to point to the (new)
|
||||||
|
/// currently-designated field.
|
||||||
|
static void ExpandAnonymousFieldDesignator(Sema &SemaRef,
|
||||||
|
DesignatedInitExpr *DIE,
|
||||||
|
unsigned DesigIdx,
|
||||||
|
FieldDecl *Field,
|
||||||
|
RecordDecl::field_iterator &FieldIter,
|
||||||
|
unsigned &FieldIndex) {
|
||||||
|
typedef DesignatedInitExpr::Designator Designator;
|
||||||
|
|
||||||
|
// Build the path from the current object to the member of the
|
||||||
|
// anonymous struct/union (backwards).
|
||||||
|
llvm::SmallVector<FieldDecl *, 4> Path;
|
||||||
|
SemaRef.BuildAnonymousStructUnionMemberPath(Field, Path);
|
||||||
|
|
||||||
|
// Build the replacement designators.
|
||||||
|
llvm::SmallVector<Designator, 4> Replacements;
|
||||||
|
for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
|
||||||
|
FI = Path.rbegin(), FIEnd = Path.rend();
|
||||||
|
FI != FIEnd; ++FI) {
|
||||||
|
if (FI + 1 == FIEnd)
|
||||||
|
Replacements.push_back(Designator((IdentifierInfo *)0,
|
||||||
|
DIE->getDesignator(DesigIdx)->getDotLoc(),
|
||||||
|
DIE->getDesignator(DesigIdx)->getFieldLoc()));
|
||||||
|
else
|
||||||
|
Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(),
|
||||||
|
SourceLocation()));
|
||||||
|
Replacements.back().setField(*FI);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand the current designator into the set of replacement
|
||||||
|
// designators, so we have a full subobject path down to where the
|
||||||
|
// member of the anonymous struct/union is actually stored.
|
||||||
|
DIE->ExpandDesignator(DesigIdx, &Replacements[0],
|
||||||
|
&Replacements[0] + Replacements.size());
|
||||||
|
|
||||||
|
// Update FieldIter/FieldIndex;
|
||||||
|
RecordDecl *Record = cast<RecordDecl>(Path.back()->getDeclContext());
|
||||||
|
FieldIter = Record->field_begin(SemaRef.Context);
|
||||||
|
FieldIndex = 0;
|
||||||
|
for (RecordDecl::field_iterator FEnd = Record->field_end(SemaRef.Context);
|
||||||
|
FieldIter != FEnd; ++FieldIter) {
|
||||||
|
if (FieldIter->isUnnamedBitfield())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (*FieldIter == Path.back())
|
||||||
|
return;
|
||||||
|
|
||||||
|
++FieldIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false && "Unable to find anonymous struct/union field");
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Check the well-formedness of a C99 designated initializer.
|
/// @brief Check the well-formedness of a C99 designated initializer.
|
||||||
///
|
///
|
||||||
/// Determines whether the designated initializer @p DIE, which
|
/// Determines whether the designated initializer @p DIE, which
|
||||||
|
@ -1138,6 +1196,7 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
|
||||||
// Note: we perform a linear search of the fields here, despite
|
// Note: we perform a linear search of the fields here, despite
|
||||||
// the fact that we have a faster lookup method, because we always
|
// the fact that we have a faster lookup method, because we always
|
||||||
// need to compute the field's index.
|
// need to compute the field's index.
|
||||||
|
FieldDecl *KnownField = D->getField();
|
||||||
IdentifierInfo *FieldName = D->getFieldName();
|
IdentifierInfo *FieldName = D->getFieldName();
|
||||||
unsigned FieldIndex = 0;
|
unsigned FieldIndex = 0;
|
||||||
RecordDecl::field_iterator
|
RecordDecl::field_iterator
|
||||||
|
@ -1147,40 +1206,50 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
|
||||||
if (Field->isUnnamedBitfield())
|
if (Field->isUnnamedBitfield())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (Field->getIdentifier() == FieldName)
|
if (KnownField == *Field || Field->getIdentifier() == FieldName)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
++FieldIndex;
|
++FieldIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Field == FieldEnd) {
|
if (Field == FieldEnd) {
|
||||||
// We did not find the field we're looking for. Produce a
|
// There was no normal field in the struct with the designated
|
||||||
// suitable diagnostic and return a failure.
|
// name. Perform another lookup for this name, which may find
|
||||||
|
// something that we can't designate (e.g., a member function),
|
||||||
|
// may find nothing, or may find a member of an anonymous
|
||||||
|
// struct/union.
|
||||||
DeclContext::lookup_result Lookup
|
DeclContext::lookup_result Lookup
|
||||||
= RT->getDecl()->lookup(SemaRef.Context, FieldName);
|
= RT->getDecl()->lookup(SemaRef.Context, FieldName);
|
||||||
if (Lookup.first == Lookup.second) {
|
if (Lookup.first == Lookup.second) {
|
||||||
// Name lookup didn't find anything.
|
// Name lookup didn't find anything.
|
||||||
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
|
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
|
||||||
<< FieldName << CurrentObjectType;
|
<< FieldName << CurrentObjectType;
|
||||||
|
++Index;
|
||||||
|
return true;
|
||||||
|
} else if (!KnownField && isa<FieldDecl>(*Lookup.first) &&
|
||||||
|
cast<RecordDecl>((*Lookup.first)->getDeclContext())
|
||||||
|
->isAnonymousStructOrUnion()) {
|
||||||
|
// Handle an field designator that refers to a member of an
|
||||||
|
// anonymous struct or union.
|
||||||
|
ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx,
|
||||||
|
cast<FieldDecl>(*Lookup.first),
|
||||||
|
Field, FieldIndex);
|
||||||
} else {
|
} else {
|
||||||
// Name lookup found something, but it wasn't a field.
|
// Name lookup found something, but it wasn't a field.
|
||||||
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
|
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
|
||||||
<< FieldName;
|
<< FieldName;
|
||||||
SemaRef.Diag((*Lookup.first)->getLocation(),
|
SemaRef.Diag((*Lookup.first)->getLocation(),
|
||||||
diag::note_field_designator_found);
|
diag::note_field_designator_found);
|
||||||
}
|
|
||||||
|
|
||||||
++Index;
|
++Index;
|
||||||
return true;
|
return true;
|
||||||
} else if (cast<RecordDecl>((*Field)->getDeclContext())
|
}
|
||||||
|
} else if (!KnownField &&
|
||||||
|
cast<RecordDecl>((*Field)->getDeclContext())
|
||||||
->isAnonymousStructOrUnion()) {
|
->isAnonymousStructOrUnion()) {
|
||||||
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_anon_class)
|
ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, *Field,
|
||||||
<< FieldName
|
Field, FieldIndex);
|
||||||
<< (cast<RecordDecl>((*Field)->getDeclContext())->isUnion()? 2 :
|
D = DIE->getDesignator(DesigIdx);
|
||||||
(int)SemaRef.getLangOptions().CPlusPlus);
|
|
||||||
SemaRef.Diag((*Field)->getLocation(), diag::note_field_designator_found);
|
|
||||||
++Index;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All of the fields of a union are located at the same place in
|
// All of the fields of a union are located at the same place in
|
||||||
|
@ -1284,6 +1353,10 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList,
|
||||||
if (!FinishSubobjectInit)
|
if (!FinishSubobjectInit)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// We've already initialized something in the union; we're done.
|
||||||
|
if (RT->getDecl()->isUnion())
|
||||||
|
return hadError;
|
||||||
|
|
||||||
// Check the remaining fields within this class/struct/union subobject.
|
// Check the remaining fields within this class/struct/union subobject.
|
||||||
bool prevHadError = hadError;
|
bool prevHadError = hadError;
|
||||||
CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index,
|
CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index,
|
||||||
|
|
|
@ -187,3 +187,37 @@ const union wibble wobble = { .arr2[0] = 0xffff,
|
||||||
.arr2[2] = 0xffff };
|
.arr2[2] = 0xffff };
|
||||||
|
|
||||||
const union wibble wobble2 = { .arr2 = {4, 5, 6}, 7 }; // expected-warning{{excess elements in union initializer}}
|
const union wibble wobble2 = { .arr2 = {4, 5, 6}, 7 }; // expected-warning{{excess elements in union initializer}}
|
||||||
|
|
||||||
|
// PR3778
|
||||||
|
struct s {
|
||||||
|
union { int i; };
|
||||||
|
};
|
||||||
|
struct s si = {
|
||||||
|
{ .i = 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
double d0;
|
||||||
|
char c0;
|
||||||
|
float f0;
|
||||||
|
int i0;
|
||||||
|
|
||||||
|
struct Enigma {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
double *double_ptr;
|
||||||
|
char *string;
|
||||||
|
};
|
||||||
|
float *float_ptr;
|
||||||
|
};
|
||||||
|
int *int_ptr;
|
||||||
|
};
|
||||||
|
char *string2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Enigma enigma = {
|
||||||
|
.double_ptr = &d0, &c0,
|
||||||
|
&f0, // expected-note{{previous}}
|
||||||
|
&c0,
|
||||||
|
.float_ptr = &f0 // expected-warning{{overrides}}
|
||||||
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче