[cfe-commits] r66685 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaCXX/class.cpp test/SemaTemplate/instantiate-field.cpp

Douglas Gregor dgregor at apple.com
Wed Mar 11 11:59:21 PDT 2009


Author: dgregor
Date: Wed Mar 11 13:59:21 2009
New Revision: 66685

URL: http://llvm.org/viewvc/llvm-project?rev=66685&view=rev
Log:
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.


Added:
    cfe/trunk/test/SemaTemplate/instantiate-field.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/SemaCXX/class.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=66685&r1=66684&r2=66685&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Mar 11 13:59:21 2009
@@ -253,7 +253,7 @@
 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 @@
      "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")

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=66685&r1=66684&r2=66685&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Mar 11 13:59:21 2009
@@ -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,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=66685&r1=66684&r2=66685&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Mar 11 13:59:21 2009
@@ -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);
+
+  // 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;
 }
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=66685&r1=66684&r2=66685&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Mar 11 13:59:21 2009
@@ -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);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=66685&r1=66684&r2=66685&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Mar 11 13:59:21 2009
@@ -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;
 

Modified: cfe/trunk/test/SemaCXX/class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=66685&r1=66684&r2=66685&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/class.cpp (original)
+++ cfe/trunk/test/SemaCXX/class.cpp Wed Mar 11 13:59:21 2009
@@ -27,8 +27,8 @@
   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 };
 

Added: cfe/trunk/test/SemaTemplate/instantiate-field.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-field.cpp?rev=66685&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-field.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-field.cpp Wed Mar 11 13:59:21 2009
@@ -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}}
+}





More information about the cfe-commits mailing list