aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-11 18:59:21 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-11 18:59:21 +0000
commit3cf538d5c49bbebac1afa6f4a5010e3d877440bb (patch)
tree02847e5829ae346324a17c3d529e6c5ae5ad4057
parentdb51a55c4922b055a90a370ce9906455887a8564 (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.def4
-rw-r--r--lib/Sema/Sema.h5
-rw-r--r--lib/Sema/SemaDecl.cpp128
-rw-r--r--lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp49
-rw-r--r--test/SemaCXX/class.cpp4
-rw-r--r--test/SemaTemplate/instantiate-field.cpp28
7 files changed, 164 insertions, 57 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def
index 2c024de380..96dc3ab283 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.def
+++ b/include/clang/Basic/DiagnosticSemaKinds.def
@@ -253,7 +253,7 @@ DIAG(err_static_not_bitfield, ERROR,
DIAG(err_typedef_not_bitfield, ERROR,
"typedef member %0 cannot be a bit-field")
DIAG(err_not_integral_type_bitfield, ERROR,
- "bit-field %0 has non-integral type")
+ "bit-field %0 has non-integral type %1")
DIAG(err_member_initialization, ERROR,
"%0 can only be initialized if it is a static const integral data member")
DIAG(err_member_function_initialization, ERROR,
@@ -655,6 +655,8 @@ DIAG(note_template_class_instantiation_here, NOTE,
"in instantiation of template class %0 requested here")
DIAG(note_default_arg_instantiation_here, NOTE,
"in instantiation of default argument for '%0' required here")
+DIAG(err_field_instantiates_to_function, ERROR,
+ "data member instantiated with function type %0")
DIAG(err_unexpected_typedef, ERROR,
"unexpected type name %0: expected expression")
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 2e02004113..1a66cc0324 100644
--- a/lib/Sema/Sema.h
+++ b/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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 03d00b83a3..8c82c5cad3 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/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/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b708598c62..6df1600c69 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/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/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index d630e801b0..5800ab9265 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/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;
diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp
index 44ec70f07c..776fb091da 100644
--- a/test/SemaCXX/class.cpp
+++ b/test/SemaCXX/class.cpp
@@ -27,8 +27,8 @@ public:
typedef int func();
func tm;
func *ptm;
- func btm : 1; // expected-error {{error: bit-field 'btm' has non-integral type}}
- NestedC bc : 1; // expected-error {{error: bit-field 'bc' has non-integral type}}
+ func btm : 1; // expected-error {{bit-field 'btm' has non-integral type}}
+ NestedC bc : 1; // expected-error {{bit-field 'bc' has non-integral type}}
enum E1 { en1, en2 };
diff --git a/test/SemaTemplate/instantiate-field.cpp b/test/SemaTemplate/instantiate-field.cpp
new file mode 100644
index 0000000000..dbfbd47060
--- /dev/null
+++ b/test/SemaTemplate/instantiate-field.cpp
@@ -0,0 +1,28 @@
+// RUN: clang -fsyntax-only -verify %s
+
+template<typename T>
+struct X {
+ int x;
+ T y; // expected-error{{data member instantiated with function type}}
+ T* z;
+ T bitfield : 12; // expected-error{{bit-field 'bitfield' has non-integral type 'float'}} \
+ // expected-error{{data member instantiated with function type}}
+
+ mutable T x2; // expected-error{{data member instantiated with function type}}
+};
+
+void test1(const X<int> *xi) {
+ int i1 = xi->x;
+ const int &i2 = xi->y;
+ int* ip1 = xi->z;
+ int i3 = xi->bitfield;
+ xi->x2 = 17;
+}
+
+void test2(const X<float> *xf) {
+ (void)xf->x; // expected-note{{in instantiation of template class 'struct X<float>' requested here}}
+}
+
+void test3(const X<int(int)> *xf) {
+ (void)xf->x; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}}
+}