diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 128 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 49 |
4 files changed, 131 insertions, 54 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 2e02004113f..1a66cc03242 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -371,6 +371,11 @@ public: FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth); + FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, + RecordDecl *Record, SourceLocation Loc, + bool Mutable, Expr *BitfieldWidth, + NamedDecl *PrevDecl, + Declarator *D = 0); virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, ExprTy *BitfieldWidth, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 03d00b83a3c..8c82c5cad33 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3219,14 +3219,19 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, QualType FieldTy, const Expr *BitWidth) { // C99 6.7.2.1p4 - verify the field type. // C++ 9.6p3: A bit-field shall have integral or enumeration type. - if (!FieldTy->isIntegralType()) { + if (!FieldTy->isDependentType() && !FieldTy->isIntegralType()) { // Handle incomplete types with specific error. if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) return true; return Diag(FieldLoc, diag::err_not_integral_type_bitfield) - << FieldName << BitWidth->getSourceRange(); + << FieldName << FieldTy << BitWidth->getSourceRange(); } - + + // If the bit-width is type- or value-dependent, don't try to check + // it now. + if (BitWidth->isValueDependent() || BitWidth->isTypeDependent()) + return false; + llvm::APSInt Value; if (VerifyIntegerConstantExpression(BitWidth, &Value)) return true; @@ -3238,11 +3243,13 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, if (Value.isNegative()) return Diag(FieldLoc, diag::err_bitfield_has_negative_width) << FieldName; - uint64_t TypeSize = Context.getTypeSize(FieldTy); - // FIXME: We won't need the 0 size once we check that the field type is valid. - if (TypeSize && Value.getZExtValue() > TypeSize) - return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) - << FieldName << (unsigned)TypeSize; + if (!FieldTy->isDependentType()) { + uint64_t TypeSize = Context.getTypeSize(FieldTy); + // FIXME: We won't need the 0 size once we check that the field type is valid. + if (TypeSize && Value.getZExtValue() > TypeSize) + return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) + << FieldName << (unsigned)TypeSize; + } return false; } @@ -3264,11 +3271,56 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, IdentifierInfo *II = D.getIdentifier(); SourceLocation Loc = DeclStart; if (II) Loc = D.getIdentifierLoc(); - + QualType T = GetTypeForDeclarator(D, S); - assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); + + if (getLangOptions().CPlusPlus) + CheckExtraCXXDefaultArguments(D); + + NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); + if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) + PrevDecl = 0; + + FieldDecl *NewFD + = CheckFieldDecl(II, T, Record, Loc, + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable, + BitWidth, PrevDecl, &D); + if (NewFD->isInvalidDecl() && PrevDecl) { + // Don't introduce NewFD into scope; there's already something + // with the same name in the same scope. + } else if (II) { + PushOnScopeChains(NewFD, S); + } else + Record->addDecl(NewFD); + + return NewFD; +} + +/// \brief Build a new FieldDecl and check its well-formedness. +/// +/// This routine builds a new FieldDecl given the fields name, type, +/// record, etc. \p PrevDecl should refer to any previous declaration +/// with the same name and in the same scope as the field to be +/// created. +/// +/// \returns a new FieldDecl. +/// +/// \todo The Declarator argument is a hack. It will be removed once +FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, + RecordDecl *Record, SourceLocation Loc, + bool Mutable, Expr *BitWidth, + NamedDecl *PrevDecl, + Declarator *D) { + IdentifierInfo *II = Name.getAsIdentifierInfo(); bool InvalidDecl = false; + // If we receive a broken type, recover by assuming 'int' and + // marking this declaration as invalid. + if (T.isNull()) { + InvalidDecl = true; + T = Context.IntTy; + } + // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. if (T->isVariablyModifiedType()) { @@ -3288,53 +3340,37 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, } } - if (BitWidth) { - if (VerifyBitField(Loc, II, T, BitWidth)) { - InvalidDecl = true; - DeleteExpr(BitWidth); - BitWidth = 0; - } - } else { - // Not a bitfield. - - // validate II. - + // If this is declared as a bit-field, check the bit-field. + if (BitWidth && VerifyBitField(Loc, II, T, BitWidth)) { + InvalidDecl = true; + DeleteExpr(BitWidth); + BitWidth = 0; } - FieldDecl *NewFD = FieldDecl::Create(Context, Record, - Loc, II, T, BitWidth, - D.getDeclSpec().getStorageClassSpec() == - DeclSpec::SCS_mutable); + FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, BitWidth, + Mutable); - if (II) { - NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); - if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S) - && !isa<TagDecl>(PrevDecl)) { - Diag(Loc, diag::err_duplicate_member) << II; - Diag(PrevDecl->getLocation(), diag::note_previous_declaration); - NewFD->setInvalidDecl(); - Record->setInvalidDecl(); - } + if (PrevDecl && !isa<TagDecl>(PrevDecl)) { + Diag(Loc, diag::err_duplicate_member) << II; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + Record->setInvalidDecl(); } - if (getLangOptions().CPlusPlus) { - CheckExtraCXXDefaultArguments(D); - if (!T->isPODType()) - cast<CXXRecordDecl>(Record)->setPOD(false); - } + if (getLangOptions().CPlusPlus && !T->isPODType()) + cast<CXXRecordDecl>(Record)->setPOD(false); + + // FIXME: We need to pass in the attributes given an AST + // representation, not a parser representation. + if (D) + ProcessDeclAttributes(NewFD, *D); - ProcessDeclAttributes(NewFD, D); if (T.isObjCGCWeak()) Diag(Loc, diag::warn_attribute_weak_on_field); - if (D.getInvalidType() || InvalidDecl) + if (InvalidDecl) NewFD->setInvalidDecl(); - if (II) { - PushOnScopeChains(NewFD, S); - } else - Record->addDecl(NewFD); - return NewFD; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b708598c620..6df1600c695 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -573,7 +573,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // A function typedef ("typedef int f(); f a;"). // C++ 9.6p3: A bit-field shall have integral or enumeration type. Diag(Loc, diag::err_not_integral_type_bitfield) - << Name << BitWidth->getSourceRange(); + << Name << cast<ValueDecl>(Member)->getType() + << BitWidth->getSourceRange(); } DeleteExpr(BitWidth); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index d630e801b02..5800ab9265a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -664,7 +664,7 @@ Sema::InstantiateClassTemplateSpecialization( // instantiation. Should this be a typedef or something like it? RecordDecl *Pattern = Template->getTemplatedDecl(); - + llvm::SmallVector<DeclTy *, 32> Fields; for (RecordDecl::decl_iterator Member = Pattern->decls_begin(), MemberEnd = Pattern->decls_end(); Member != MemberEnd; ++Member) { @@ -690,18 +690,53 @@ Sema::InstantiateClassTemplateSpecialization( Typedef->getIdentifier(), T); ClassTemplateSpec->addDecl(New); + } + else if (FieldDecl *Field = dyn_cast<FieldDecl>(*Member)) { + // FIXME: Simplified instantiation of fields needs to be made + // "real". + QualType T = Field->getType(); + if (T->isDependentType()) { + T = InstantiateType(T, ClassTemplateSpec->getTemplateArgs(), + ClassTemplateSpec->getNumTemplateArgs(), + Field->getLocation(), + Field->getDeclName()); + if (!T.isNull() && T->isFunctionType()) { + // C++ [temp.arg.type]p3: + // If a declaration acquires a function type through a type + // dependent on a template-parameter and this causes a + // declaration that does not use the syntactic form of a + // function declarator to have function type, the program is + // ill-formed. + Diag(Field->getLocation(), diag::err_field_instantiates_to_function) + << T; + T = QualType(); + } + } + + FieldDecl *New = CheckFieldDecl(Field->getDeclName(), T, + ClassTemplateSpec, + Field->getLocation(), + Field->isMutable(), + Field->getBitWidth(), + 0); + if (New) { + ClassTemplateSpec->addDecl(New); + Fields.push_back(New); + + if (New->isInvalidDecl()) + Invalid = true; + } } } - // FIXME: Instantiate all of the members. - + // Finish checking fields. + ActOnFields(0, ClassTemplateSpec->getLocation(), ClassTemplateSpec, + &Fields[0], Fields.size(), SourceLocation(), SourceLocation(), + 0); + // Add any implicitly-declared members that we might need. AddImplicitlyDeclaredMembersToClass(ClassTemplateSpec); - // Finish the definition of this instantiation. - // FIXME: ActOnFields does more checking, which we'll eventually need. - ClassTemplateSpec->completeDefinition(Context); - // Exit the scope of this instantiation. CurContext = PreviousContext; |