]> granicus.if.org Git - clang/commitdiff
Introduce a method to get from an anonymous struct or union record declaration
authorJohn McCall <rjmccall@apple.com>
Fri, 21 May 2010 01:17:40 +0000 (01:17 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 21 May 2010 01:17:40 +0000 (01:17 +0000)
to the associated object declaration.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104309 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
lib/AST/Decl.cpp
lib/Sema/SemaExpr.cpp

index db23342b00b73f10a7c4f7f65a2936cd2cd717d2..e95f697104914918e916fc7975d2a0a88ac47d06 100644 (file)
@@ -2021,6 +2021,11 @@ public:
     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; }
 
index 695a8b8b51480d81198fd8cf19003cbc0ed3a5e7..ffdcb471d0822585cc133371432ca68cb962e86c 100644 (file)
@@ -1627,6 +1627,17 @@ void RecordDecl::completeDefinition() {
   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;
+}
+
 //===----------------------------------------------------------------------===//
 // BlockDecl Implementation
 //===----------------------------------------------------------------------===//
index 9d8fe9c85f0ee308095459575f6830d052176d9e..933a696bdccb5d31052407d8f056133f780103fd 100644 (file)
@@ -496,35 +496,6 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
                                    D, Loc, Ty));
 }
 
-/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or
-/// variable corresponding to the anonymous union or struct whose type
-/// is Record.
-static Decl *getObjectForAnonymousRecordDecl(ASTContext &Context,
-                                             RecordDecl *Record) {
-  assert(Record->isAnonymousStructOrUnion() &&
-         "Record must be an anonymous struct or union!");
-
-  // FIXME: Once Decls are directly linked together, this will be an O(1)
-  // operation rather than a slow walk through DeclContext's vector (which
-  // itself will be eliminated). DeclGroups might make this even better.
-  DeclContext *Ctx = Record->getDeclContext();
-  for (DeclContext::decl_iterator D = Ctx->decls_begin(),
-                               DEnd = Ctx->decls_end();
-       D != DEnd; ++D) {
-    if (*D == Record) {
-      // The object for the anonymous struct/union directly
-      // follows its type in the list of declarations.
-      ++D;
-      assert(D != DEnd && "Missing object for anonymous record");
-      assert(!cast<NamedDecl>(*D)->getDeclName() && "Decl should be unnamed");
-      return *D;
-    }
-  }
-
-  assert(false && "Missing object for anonymous record");
-  return 0;
-}
-
 /// \brief Given a field that represents a member of an anonymous
 /// struct/union, build the path from that field's context to the
 /// actual member.
@@ -549,7 +520,7 @@ VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
   DeclContext *Ctx = Field->getDeclContext();
   do {
     RecordDecl *Record = cast<RecordDecl>(Ctx);
-    Decl *AnonObject = getObjectForAnonymousRecordDecl(Context, Record);
+    ValueDecl *AnonObject = Record->getAnonymousStructOrUnionObject();
     if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject))
       Path.push_back(AnonField);
     else {