[cfe-commits] r122387 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/RecursiveASTVisitor.h lib/AST/Decl.cpp lib/Sema/SemaInit.cpp

Francois Pichet pichet2000 at gmail.com
Tue Dec 21 19:46:10 PST 2010


Author: fpichet
Date: Tue Dec 21 21:46:10 2010
New Revision: 122387

URL: http://llvm.org/viewvc/llvm-project?rev=122387&view=rev
Log:
Redesign the way anonymous fields are handled in designated-initializers.
Previously designated anonymous fields were found via name lookup. This redesign uses the fact that an IndirectFieldDecl declaration will always follow an anonymous implicit field to remove the special case of name lookup. 

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=122387&r1=122386&r2=122387&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Dec 21 21:46:10 2010
@@ -2405,11 +2405,6 @@
     AnonymousStructOrUnion = Anon;
   }
 
-  ValueDecl *getAnonymousStructOrUnionObject();
-  const ValueDecl *getAnonymousStructOrUnionObject() const {
-    return const_cast<RecordDecl*>(this)->getAnonymousStructOrUnionObject();
-  }
-
   bool hasObjectMember() const { return HasObjectMember; }
   void setHasObjectMember (bool val) { HasObjectMember = val; }
 

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=122387&r1=122386&r2=122387&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Dec 21 21:46:10 2010
@@ -1306,11 +1306,7 @@
     RecordDecl *D) {
   // We shouldn't traverse D->getTypeForDecl(); it's a result of
   // declaring the type, not something that was written in the source.
-  //
-  // The anonymous struct or union object is the variable or field
-  // whose type is the anonymous struct or union.  We shouldn't
-  // traverse D->getAnonymousStructOrUnionObject(), as it's not
-  // something that is explicitly written in the source.
+
   TRY_TO(TraverseNestedNameSpecifier(D->getQualifier()));
   return true;
 }

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=122387&r1=122386&r2=122387&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Dec 21 21:46:10 2010
@@ -2005,17 +2005,6 @@
   TagDecl::completeDefinition();
 }
 
-ValueDecl *RecordDecl::getAnonymousStructOrUnionObject() {
-  // Force the decl chain to come into existence properly.
-  if (!getNextDeclInContext()) getParent()->decls_begin();
-
-  assert(isAnonymousStructOrUnion());
-  ValueDecl *D = cast<ValueDecl>(getNextDeclInContext());
-  assert(D->getType()->isRecordType());
-  assert(D->getType()->getAs<RecordType>()->getDecl() == this);
-  return D;
-}
-
 void RecordDecl::LoadFieldsFromExternalStorage() const {
   ExternalASTSource *Source = getASTContext().getExternalSource();
   assert(hasExternalLexicalStorage() && Source && "No external storage?");

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=122387&r1=122386&r2=122387&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Dec 21 21:46:10 2010
@@ -1194,55 +1194,29 @@
                           StructuredList, StructuredIndex);
 }
 
-/// \brief Similar to Sema::BuildAnonymousStructUnionMemberPath() but builds a
-/// relative path and has strict checks.
-static void BuildRelativeAnonymousStructUnionMemberPath(FieldDecl *Field,
-                                    llvm::SmallVectorImpl<FieldDecl *> &Path,
-                                    DeclContext *BaseDC) {
-  Path.push_back(Field);
-  for (DeclContext *Ctx = Field->getDeclContext();
-       !Ctx->Equals(BaseDC);
-       Ctx = Ctx->getParent()) {
-    ValueDecl *AnonObject =
-      cast<RecordDecl>(Ctx)->getAnonymousStructOrUnionObject();
-    FieldDecl *AnonField = cast<FieldDecl>(AnonObject);
-    Path.push_back(AnonField);
-  }
-}
-
 /// \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,
-                                           DeclContext *BaseDC) {
+                                           IndirectFieldDecl *IndirectField) {
   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;
-  BuildRelativeAnonymousStructUnionMemberPath(Field, Path, BaseDC);
-
   // 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)
+  for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(),
+       PE = IndirectField->chain_end(); PI != PE; ++PI) {
+    if (PI + 1 == PE)
       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);
+    assert(isa<FieldDecl>(*PI));
+    Replacements.back().setField(cast<FieldDecl>(*PI));
   }
 
   // Expand the current designator into the set of replacement
@@ -1250,23 +1224,20 @@
   // member of the anonymous struct/union is actually stored.
   DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0],
                         &Replacements[0] + Replacements.size());
+}
 
-  // Update FieldIter/FieldIndex;
-  RecordDecl *Record = cast<RecordDecl>(Path.back()->getDeclContext());
-  FieldIter = Record->field_begin();
-  FieldIndex = 0;
-  for (RecordDecl::field_iterator FEnd = Record->field_end();
-       FieldIter != FEnd; ++FieldIter) {
-    if (FieldIter->isUnnamedBitfield())
-        continue;
-
-    if (*FieldIter == Path.back())
-      return;
-
-    ++FieldIndex;
+/// \brief Given an implicit anonymous field, search the IndirectField that 
+///  corresponds to FieldName.
+static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField,
+                                                 IdentifierInfo *FieldName) {
+  assert(AnonField->isAnonymousStructOrUnion());
+  Decl *NextDecl = AnonField->getNextDeclInContext();
+  while (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(NextDecl)) {
+    if (FieldName && FieldName == IF->getAnonField()->getIdentifier())
+      return IF;
+    NextDecl = NextDecl->getNextDeclInContext();
   }
-
-  assert(false && "Unable to find anonymous struct/union field");
+  return 0;
 }
 
 /// @brief Check the well-formedness of a C99 designated initializer.
@@ -1386,7 +1357,17 @@
     for (; Field != FieldEnd; ++Field) {
       if (Field->isUnnamedBitfield())
         continue;
-
+      
+      // If we find a field representing an anonymous field, look in the
+      // IndirectFieldDecl that follow for the designated initializer.
+      if (!KnownField && Field->isAnonymousStructOrUnion()) {
+        if (IndirectFieldDecl *IF =
+            FindIndirectFieldDesignator(*Field, FieldName)) {
+          ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF);
+          D = DIE->getDesignator(DesigIdx);
+          break;
+        }
+      }
       if (KnownField && KnownField == *Field)
         break;
       if (FieldName && FieldName == Field->getIdentifier())
@@ -1427,16 +1408,8 @@
           ++Index;
           return true;
         }
-      } else if (!KnownField) {
-        // Determine whether we found a field at all.
-        ReplacementField = dyn_cast<FieldDecl>(*Lookup.first);
-        
-        // Check if ReplacementField is an anonymous field. 
-        if (!ReplacementField)
-          if (IndirectFieldDecl* IField = dyn_cast<IndirectFieldDecl>(*Lookup.first))
-            ReplacementField = IField->getAnonField();
       }
-
+ 
       if (!ReplacementField) {
         // Name lookup found something, but it wasn't a field.
         SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield)
@@ -1447,16 +1420,7 @@
         return true;
       }
 
-      if (!KnownField && 
-          cast<RecordDecl>((ReplacementField)->getDeclContext())
-                                                 ->isAnonymousStructOrUnion()) {
-        // Handle an field designator that refers to a member of an
-        // anonymous struct or union. This is a C1X feature.
-        ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx,
-                                       ReplacementField,
-                                       Field, FieldIndex, RT->getDecl());
-        D = DIE->getDesignator(DesigIdx);
-      } else if (!KnownField) {
+      if (!KnownField) {
         // The replacement field comes from typo correction; find it
         // in the list of fields.
         FieldIndex = 0;





More information about the cfe-commits mailing list