Implement basic template instantiation for fields. Reshuffle checking
for FieldDecls so that the parser and the template instantiation make
use of the same semantic checking module.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66685 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 2e02004..1a66cc0 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -371,6 +371,11 @@
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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 03d00b8..8c82c5c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3219,14 +3219,19 @@
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 @@
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 @@
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 @@
}
}
- 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);
- ProcessDeclAttributes(NewFD, D);
+ // FIXME: We need to pass in the attributes given an AST
+ // representation, not a parser representation.
+ if (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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b708598..6df1600 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -573,7 +573,8 @@
// 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/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index d630e80..5800ab9 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -664,7 +664,7 @@
// 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 @@
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;