]> granicus.if.org Git - clang/commitdiff
Simplify the way in which we inject the names of tag definitions and
authorDouglas Gregor <dgregor@apple.com>
Tue, 3 Feb 2009 00:34:39 +0000 (00:34 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 3 Feb 2009 00:34:39 +0000 (00:34 +0000)
elaborated-type-specifier declarations into outer scopes while
retaining their proper lexical scope. This way is simpler and more
consistent with the way DeclContexts work, and also fixes

  http://llvm.org/bugs/show_bug.cgi?id=3430

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

lib/Sema/SemaDecl.cpp
test/Sema/struct-decl.c

index d2140b22675780adad4ec6ba7b23c9739b5f4df7..d7c5fa6860725b74f612741b191718ffdb4e97ca 100644 (file)
@@ -839,6 +839,11 @@ Sema::DeclTy *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
         }
       } else if ((*Mem)->isImplicit()) {
         // Any implicit members are fine.
+      } else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
+        // This is a type that showed up in an
+        // elaborated-type-specifier inside the anonymous struct or
+        // union, but which actually declares a type outside of the
+        // anonymous struct or union. It's okay.
       } else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) {
         if (!MemRecord->isAnonymousStructOrUnion() &&
             MemRecord->getDeclName()) {
@@ -2791,7 +2796,6 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
   
   DeclContext *SearchDC = CurContext;
   DeclContext *DC = CurContext;
-  DeclContext *LexicalContext = CurContext;
   Decl *PrevDecl = 0;
 
   bool Invalid = false;
@@ -2806,6 +2810,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
     }
 
     DC = static_cast<DeclContext*>(SS.getScopeRep());
+    SearchDC = DC;
     // Look-up name inside 'foo::'.
     PrevDecl = dyn_cast_or_null<TagDecl>(
                      LookupQualifiedName(DC, Name, LookupTagName).getAsDecl());
@@ -2944,9 +2949,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
     // Find the context where we'll be declaring the tag.
     // FIXME: We would like to maintain the current DeclContext as the
     // lexical context, 
-    while (DC->isRecord())
-      DC = DC->getParent();
-    LexicalContext = DC;
+    while (SearchDC->isRecord())
+      SearchDC = SearchDC->getParent();
 
     // Find the scope where we'll be declaring the tag.
     while (S->isClassScope() || 
@@ -2972,7 +2976,7 @@ CreateNewDecl:
   if (Kind == TagDecl::TK_enum) {
     // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
     // enum X { A, B, C } D;    D should chain to X.
-    New = EnumDecl::Create(Context, DC, Loc, Name, 
+    New = EnumDecl::Create(Context, SearchDC, Loc, Name, 
                            cast_or_null<EnumDecl>(PrevDecl));
     // If this is an undefined enum, warn.
     if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum);
@@ -2983,10 +2987,10 @@ CreateNewDecl:
     // struct X { int A; } D;    D should chain to X.
     if (getLangOptions().CPlusPlus)
       // FIXME: Look for a way to use RecordDecl for simple structs.
-      New = CXXRecordDecl::Create(Context, Kind, DC, Loc, Name,
+      New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name,
                                   cast_or_null<CXXRecordDecl>(PrevDecl));
     else
-      New = RecordDecl::Create(Context, Kind, DC, Loc, Name,
+      New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name,
                                cast_or_null<RecordDecl>(PrevDecl));
   }
 
@@ -3041,7 +3045,7 @@ CreateNewDecl:
 
   // Set the lexical context. If the tag has a C++ scope specifier, the
   // lexical context will be different from the semantic context.
-  New->setLexicalDeclContext(LexicalContext);
+  New->setLexicalDeclContext(CurContext);
 
   if (TK == TK_Definition)
     New->startDefinition();
@@ -3049,18 +3053,9 @@ CreateNewDecl:
   // If this has an identifier, add it to the scope stack.
   if (Name) {
     S = getNonFieldDeclScope(S);
-    
-    // Add it to the decl chain.
-    if (LexicalContext != CurContext) {
-      // FIXME: PushOnScopeChains should not rely on CurContext!
-      DeclContext *OldContext = CurContext;
-      CurContext = LexicalContext;
-      PushOnScopeChains(New, S);
-      CurContext = OldContext;
-    } else 
-      PushOnScopeChains(New, S);
+    PushOnScopeChains(New, S);
   } else {
-    LexicalContext->addDecl(New);
+    CurContext->addDecl(New);
   }
 
   return New;
index 7d7961b16c834ebee5f0f4e5729b3957697e2d83..ec006b484f0a1b742ce1fc8df3bdf894d33b1932 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: clang -fsyntax-only -verify %s
-
 // PR3459
 struct bar {
        char n[1];
@@ -9,3 +8,17 @@ struct foo {
        char name[(int)&((struct bar *)0)->n];
        char name2[(int)&((struct bar *)0)->n - 1]; //expected-error{{fields must have a constant size}}
 };
+
+// PR3430
+struct s {
+        struct st {
+                int v;
+        } *ts;
+};
+
+struct st;
+
+int foo() {
+        struct st *f;
+        return f->v + f[0].v;
+}