]> granicus.if.org Git - clang/commitdiff
Fix PR2020 by recovering by defining an anonymous enum, instead of recovering
authorChris Lattner <sabre@nondot.org>
Thu, 3 Jul 2008 03:30:58 +0000 (03:30 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 3 Jul 2008 03:30:58 +0000 (03:30 +0000)
by filling in the body of a union with enum constants.

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

lib/Sema/SemaDecl.cpp
test/Sema/enum.c

index 3b0e2e6f38c2895e98ef0cafc226d6d428f07f86..c0c3f09b8c901b257aee36a3d26704a17ddb3d58 100644 (file)
@@ -1688,35 +1688,38 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
     assert((isa<TagDecl>(PrevDecl) || isa<NamespaceDecl>(PrevDecl)) &&
             "unexpected Decl type");
     if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
-      // If this is a use of a previous tag, or if the tag is already declared in
-      // the same scope (so that the definition/declaration completes or
+      // If this is a use of a previous tag, or if the tag is already declared
+      // in the same scope (so that the definition/declaration completes or
       // rementions the tag), reuse the decl.
       if (TK == TK_Reference ||
           IdResolver.isDeclInScope(PrevDecl, CurContext, S)) {
-        // Make sure that this wasn't declared as an enum and now used as a struct
-        // or something similar.
+        // Make sure that this wasn't declared as an enum and now used as a
+        // struct or something similar.
         if (PrevTagDecl->getTagKind() != Kind) {
           Diag(KWLoc, diag::err_use_with_wrong_tag, Name->getName());
           Diag(PrevDecl->getLocation(), diag::err_previous_use);
-        }
-        
-        // If this is a use or a forward declaration, we're good.
-        if (TK != TK_Definition)
-          return PrevDecl;
-
-        // Diagnose attempts to redefine a tag.
-        if (PrevTagDecl->isDefinition()) {
-          Diag(NameLoc, diag::err_redefinition, Name->getName());
-          Diag(PrevDecl->getLocation(), diag::err_previous_definition);
-          // If this is a redefinition, recover by making this struct be
-          // anonymous, which will make any later references get the previous
-          // definition.
+          // Recover by making this an anonymous redefinition.
           Name = 0;
+          PrevDecl = 0;
         } else {
-          // Okay, this is definition of a previously declared or referenced tag.
-          // Move the location of the decl to be the definition site.
-          PrevDecl->setLocation(NameLoc);
-          return PrevDecl;
+          // If this is a use or a forward declaration, we're good.
+          if (TK != TK_Definition)
+            return PrevDecl;
+
+          // Diagnose attempts to redefine a tag.
+          if (PrevTagDecl->isDefinition()) {
+            Diag(NameLoc, diag::err_redefinition, Name->getName());
+            Diag(PrevDecl->getLocation(), diag::err_previous_definition);
+            // If this is a redefinition, recover by making this struct be
+            // anonymous, which will make any later references get the previous
+            // definition.
+            Name = 0;
+          } else {
+            // Okay, this is definition of a previously declared or referenced
+            // tag. Move the location of the decl to be the definition site.
+            PrevDecl->setLocation(NameLoc);
+            return PrevDecl;
+          }
         }
       }
       // If we get here, this is a definition of a new struct type in a nested
index 890b6a505b7278a2b631a4365c4e27fd316f566c..2a20d3d7d5e47b116d62a79b9c086db96385ab70 100644 (file)
@@ -28,3 +28,8 @@ int test2(int i)
 {
   ve + i;
 }
+
+// PR2020
+union u0;    // expected-error {{previous use is here}}
+enum u0 { U0A }; // expected-error {{error: use of 'u0' with tag type that does not match previous declaration}}
+