Closed by commit rL211718 (authored by @sepavloff).

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D4145

Files:
  cfe/trunk/lib/AST/Decl.cpp
  cfe/trunk/lib/Sema/SemaDecl.cpp
  cfe/trunk/test/Sema/decl-in-prototype.c
  cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp
Index: cfe/trunk/lib/Sema/SemaDecl.cpp
===================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp
+++ cfe/trunk/lib/Sema/SemaDecl.cpp
@@ -10874,11 +10874,6 @@
       while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
         SearchDC = SearchDC->getParent();
     }
-  } else if (S->isFunctionPrototypeScope()) {
-    // If this is an enum declaration in function prototype scope, set its
-    // initial context to the translation unit.
-    // FIXME: [citation needed]
-    SearchDC = Context.getTranslationUnitDecl();
   }
 
   if (Previous.isSingleResult() &&
@@ -11351,27 +11346,37 @@
     else if (!SearchDC->isFunctionOrMethod())
       New->setModulePrivate();
   }
-  
+
   // If this is a specialization of a member class (of a class template),
   // check the specialization.
   if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
     Invalid = true;
-           
-  if (Invalid)
-    New->setInvalidDecl();
-
-  if (Attr)
-    ProcessDeclAttributeList(S, New, Attr);
 
   // If we're declaring or defining a tag in function prototype scope in C,
   // note that this type can only be used within the function and add it to
   // the list of decls to inject into the function definition scope.
-  if (!getLangOpts().CPlusPlus && (Name || Kind == TTK_Enum) &&
+  if ((Name || Kind == TTK_Enum) &&
       getNonFieldDeclScope(S)->isFunctionPrototypeScope()) {
-    Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+    if (getLangOpts().CPlusPlus) {
+      // C++ [dcl.fct]p6:
+      //   Types shall not be defined in return or parameter types.
+      if (TUK == TUK_Definition && !IsTypeSpecifier) {
+        Diag(Loc, diag::err_type_defined_in_param_type)
+            << Name;
+        Invalid = true;
+      }
+    } else {
+      Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
+    }
     DeclsInPrototypeScope.push_back(New);
   }
 
+  if (Invalid)
+    New->setInvalidDecl();
+
+  if (Attr)
+    ProcessDeclAttributeList(S, New, Attr);
+
   // Set the lexical context. If the tag has a C++ scope specifier, the
   // lexical context will be different from the semantic context.
   New->setLexicalDeclContext(CurContext);
Index: cfe/trunk/lib/AST/Decl.cpp
===================================================================
--- cfe/trunk/lib/AST/Decl.cpp
+++ cfe/trunk/lib/AST/Decl.cpp
@@ -2544,6 +2544,18 @@
     NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()];
     std::copy(NewDecls.begin(), NewDecls.end(), A);
     DeclsInPrototypeScope = ArrayRef<NamedDecl *>(A, NewDecls.size());
+    // Move declarations introduced in prototype to the function context.
+    for (auto I : NewDecls) {
+      DeclContext *DC = I->getDeclContext();
+      // Forward-declared reference to an enumeration is not added to
+      // declaration scope, so skip declaration that is absent from its
+      // declaration contexts.
+      if (DC->containsDecl(I)) {
+          DC->removeDecl(I);
+          I->setDeclContext(this);
+          addDecl(I);
+      }
+    }
   }
 }
 
Index: cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp
===================================================================
--- cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp
+++ cfe/trunk/test/SemaCXX/type-definition-in-specifier.cpp
@@ -23,3 +23,44 @@
 struct S5 { int x; } f1() { return S5(); } // expected-error{{result type}}
 
 void f2(struct S6 { int x; } p); // expected-error{{parameter type}}
+
+struct pr19018 {
+  short foo6 (enum bar0 {qq} bar3); // expected-error{{cannot be defined in a parameter type}}
+};
+
+void pr19018_1 (enum e19018_1 {qq} x); // expected-error{{cannot be defined in a parameter type}}
+void pr19018_1a (enum e19018_1 {qq} x); // expected-error{{cannot be defined in a parameter type}}
+e19018_1 x2;  // expected-error{{unknown type name 'e19018_1'}}
+
+void pr19018_2 (enum {qq} x); // expected-error{{cannot be defined in a parameter type}}
+void pr19018_3 (struct s19018_2 {int qq;} x); // expected-error{{cannot be defined in a parameter type}}
+void pr19018_4 (struct {int qq;} x); // expected-error{{cannot be defined in a parameter type}}
+void pr19018_5 (struct { void qq(); } x); // expected-error{{cannot be defined in a parameter type}}
+void pr19018_5 (struct s19018_2 { void qq(); } x); // expected-error{{cannot be defined in a parameter type}}
+
+struct pr19018a {
+  static int xx;
+  void func1(enum t19018 {qq} x); // expected-error{{cannot be defined in a parameter type}}
+  void func2(enum t19018 {qq} x); // expected-error{{cannot be defined in a parameter type}}
+  void func3(enum {qq} x);        // expected-error{{cannot be defined in a parameter type}}
+  void func4(struct t19018 {int qq;} x);  // expected-error{{cannot be defined in a parameter type}}
+  void func5(struct {int qq;} x); // expected-error{{cannot be defined in a parameter type}}
+  void func6(struct { void qq(); } x); // expected-error{{cannot be defined in a parameter type}}
+  void func7(struct t19018 { void qq(); } x); // expected-error{{cannot be defined in a parameter type}}
+  void func8(struct { int qq() { return xx; }; } x); // expected-error{{cannot be defined in a parameter type}}
+  void func9(struct t19018 { int qq() { return xx; }; } x); // expected-error{{cannot be defined in a parameter type}}
+};
+
+struct s19018b {
+  void func1 (enum en_2 {qq} x); // expected-error{{cannot be defined in a parameter type}}
+  en_2 x1;  // expected-error{{unknown type name 'en_2'}}
+  void func2 (enum en_3 {qq} x); // expected-error{{cannot be defined in a parameter type}}
+  enum en_3 x2; // expected-error{{ISO C++ forbids forward references to 'enum' types}} \
+                // expected-error{{field has incomplete type 'enum en_3'}} \
+                // expected-note{{forward declaration of 'en_3'}}
+};
+
+struct pr18963 {
+  short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot be defined in a parameter type}}
+  long foo5 (float foo6 = foo4);  // expected-error{{use of undeclared identifier 'foo4'}}
+};
Index: cfe/trunk/test/Sema/decl-in-prototype.c
===================================================================
--- cfe/trunk/test/Sema/decl-in-prototype.c
+++ cfe/trunk/test/Sema/decl-in-prototype.c
@@ -31,3 +31,7 @@
     struct z d;
     d.b = 4;
 }
+
+void pr19018_1 (enum e19018 { qq } x); // expected-warning{{declaration of 'enum e19018' will not be visible outside of this function}}
+enum e19018 qq; //expected-error{{tentative definition has type 'enum e19018' that is never completed}} \
+                //expected-note{{forward declaration of 'enum e19018'}}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to